package com.lucifer.treasure.enchant.effect;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lucifer.treasure.config.SwordAuraConstants;
import com.lucifer.treasure.util.SwordAuraLogger;
import com.lucifer.treasure.util.SwordAuraRenderer;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.AttributeModifiersComponent;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ExperienceOrbEntity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 🗡️ 御剑术附魔效果 - 纯PVE系统
 * <p>
 * PVP功能已完全分离到 SwordAuraPvPSystem 类中
 */
public class SwordAuraEnchantmentEffect {

    /**
     * 武器类型枚举 - 不同武器显示不同粒子效果
     */
    public enum WeaponType {
        SWORD("剑", ParticleTypes.ENCHANT), // 经典附魔粒子
        AXE("斧", ParticleTypes.CRIT), // 暴击粒子
        TOOL("工具", ParticleTypes.SMOKE), // 烟雾粒子（稳定不闪烁）
        ROD("钓竿", ParticleTypes.FISHING), // 钓鱼粒子
        ARROW("箭", ParticleTypes.END_ROD), // 末地烛粒子
        WAND("魔杖", ParticleTypes.WITCH), // 女巫粒子
        TRIDENT("三叉戟", ParticleTypes.BUBBLE_POP), // 气泡粒子
        BOW("弓", ParticleTypes.COMPOSTER), // 堆肥桶粒子
        STICK("木棍", ParticleTypes.ASH), // 灰烬粒子
        UNKNOWN("未知", ParticleTypes.SMOKE); // 烟雾粒子

        public final String displayName;
        public final net.minecraft.particle.ParticleEffect particleType;

        WeaponType(String displayName, net.minecraft.particle.ParticleEffect particleType) {
            this.displayName = displayName;
            this.particleType = particleType;
        }
    }

    // 御剑术状态管理
    private static final Map<UUID, Boolean> AURA_ENABLED = new ConcurrentHashMap<>(); // 是否开启御剑术 - 线程安全
    private static final Map<String, Long> TARGET_ATTACK_COOLDOWN = new ConcurrentHashMap<>(); // 目标攻击冷却 - 线程安全
    private static final Map<UUID, LivingEntity> MANUAL_ATTACK_TARGETS = new ConcurrentHashMap<>(); // 手动攻击目标管理 - 线程安全

    // 悬浮剑管理 - 使用线程安全的ConcurrentHashMap
    private static final Map<String, FloatingSword> FLOATING_SWORDS = new ConcurrentHashMap<>();
    private static final Map<String, HitEffectSword> HIT_EFFECT_SWORDS = new ConcurrentHashMap<>(); // 击中效果剑
    private static int GLOBAL_SWORD_COUNTER = 0;

    // 状态持久化
    private static final Gson GSON = new Gson();

    // 🚀 事件缓存系统
    private static final Map<UUID, Set<LivingEntity>> NEARBY_ENEMIES_CACHE = new ConcurrentHashMap<>();
    private static final Map<UUID, Set<LivingEntity>> ATTACKING_ENEMIES_CACHE = new ConcurrentHashMap<>();
    private static final Map<UUID, LivingEntity> PLAYER_TARGET_CACHE = new ConcurrentHashMap<>();
    private static final Map<UUID, Long> CACHE_UPDATE_TIME = new ConcurrentHashMap<>();

    // 🎯 命中率统计系统
    private static final Map<UUID, Integer> HIT_COUNT = new ConcurrentHashMap<>(); // 击中次数
    private static final Map<UUID, Integer> TOTAL_ATTACKS = new ConcurrentHashMap<>(); // 总攻击次数
    private static final Map<UUID, Long> LAST_STATS_TIME = new ConcurrentHashMap<>(); // 上次输出统计时间

    // 🚀 玩家位置缓存系统 - 用于按需更新
    private static final Map<UUID, Vec3d> LAST_PLAYER_POS = new ConcurrentHashMap<>(); // 上次玩家位置
    private static final Map<UUID, Float> LAST_PLAYER_YAW = new ConcurrentHashMap<>(); // 上次玩家朝向
    private static final Map<UUID, Long> LAST_PARTICLE_UPDATE = new ConcurrentHashMap<>(); // 上次粒子更新时间
    private static final Map<UUID, Double> PLAYER_MOVE_SPEED = new ConcurrentHashMap<>(); // 玩家移动速度
    private static final Map<UUID, Integer> DYNAMIC_UPDATE_INTERVAL = new ConcurrentHashMap<>(); // 动态更新间隔

    // 🎯 移动速度相关常量
    private static final double SLOW_MOVE_THRESHOLD = 0.1; // 慢速移动阈值
    private static final double FAST_MOVE_THRESHOLD = 0.5; // 快速移动阈值
    private static final int SLOW_UPDATE_INTERVAL = 1; // 慢速移动时每tick更新
    private static final int NORMAL_UPDATE_INTERVAL = 2; // 正常移动时每2tick更新
    private static final int FAST_UPDATE_INTERVAL = 5; // 快速移动时每5tick更新，减少粒子密度

    // 🎵 音效冷却系统 - 防止高等级御剑术音效过于密集
    private static final Map<UUID, Long> LAST_HIT_SOUND_TIME = new ConcurrentHashMap<>(); // 上次击中音效时间

    // 🛡️ PvP保护机制 - 防止玩家间无限循环攻击
    // PVP相关功能已迁移到 SwordAuraPvPSystem 类中

    // 🔇 用于减少日志频率的缓存 - 全部使用线程安全
    private static final Map<UUID, Integer> LAST_ENEMY_COUNT = new ConcurrentHashMap<>();
    private static final Map<UUID, Long> LAST_SWORD_STATUS_LOG = new ConcurrentHashMap<>();
    private static final Map<UUID, Integer> LAST_SWORD_COUNT = new ConcurrentHashMap<>(); // 记录上次的剑数量
    private static final Map<UUID, Long> LAST_SUPER_LEVEL_LOG = new ConcurrentHashMap<>(); // 上次超级等级日志时间
    private static final int SUPER_LEVEL_LOG_INTERVAL = 5 * 20; // 每5秒最多输出一次超级等级信息

    // 🕒 悬浮剑恢复系统 - 延迟恢复让玩家看到剑数量变化
    private static final Map<String, Long> SWORD_RECOVERY_QUEUE = new ConcurrentHashMap<>(); // key:
    // playerId_swordIndex,
    // value: 恢复时间

    // 🚀 工具方法：使用常量类计算数值
    private static int calculateSwordCount(int auraLevel) {
        return SwordAuraConstants.calculateSwordCount(auraLevel);
    }

    private static float calculateSuperLevelBonus(int auraLevel) {
        return SwordAuraConstants.calculateSuperLevelDamageBonus(auraLevel);
    }

    private static float calculateExtraEffectBonus(int auraLevel) {
        if (auraLevel <= SwordAuraConstants.NORMAL_LEVEL_CAP) {
            return 0.0f;
        } else {
            int superLevels = auraLevel - SwordAuraConstants.NORMAL_LEVEL_CAP;
            return superLevels * SwordAuraConstants.EXTRA_EFFECT_BONUS_PER_LEVEL;
        }
    }

    /**
     * 🚀 计算玩家移动速度并确定动态更新间隔
     */
    private static void calculatePlayerMoveSpeedAndInterval(PlayerEntity player, ServerWorld world) {
        UUID playerId = player.getUuid();
        Vec3d currentPos = player.getPos();
        long currentTime = world.getTime();

        // 获取上次位置
        Vec3d lastPos = LAST_PLAYER_POS.get(playerId);

        if (lastPos != null) {
            // 计算移动距离和速度
            double distance = currentPos.distanceTo(lastPos);
            double speed = distance; // 每tick的移动距离

            // 更新移动速度缓存
            PLAYER_MOVE_SPEED.put(playerId, speed);

            // 根据移动速度确定更新间隔
            int updateInterval;
            if (speed <= SLOW_MOVE_THRESHOLD) {
                updateInterval = SLOW_UPDATE_INTERVAL; // 慢速或静止：每tick更新
            } else if (speed <= FAST_MOVE_THRESHOLD) {
                updateInterval = NORMAL_UPDATE_INTERVAL; // 正常移动：每2tick更新
            } else {
                updateInterval = FAST_UPDATE_INTERVAL; // 快速移动：每5tick更新，减少粒子密度
            }

            DYNAMIC_UPDATE_INTERVAL.put(playerId, updateInterval);

            // 🔧 调试信息（偶尔输出）
            if (currentTime % 100 == 0 && speed > FAST_MOVE_THRESHOLD) {
                SwordAuraLogger.log(SwordAuraLogger.LogLevel.DEBUG, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                        String.format("[%s] 快速移动检测 - 速度:%.3f 更新间隔:%dtick",
                                SwordAuraLogger.getPlayerName(player), speed, updateInterval));
            }
        }

        // 更新位置缓存
        LAST_PLAYER_POS.put(playerId, currentPos);
    }

    /**
     * 通用的移动速度计算方法 - 支持客户端和服务器端
     */
    private static void calculatePlayerMoveSpeedAndInterval(PlayerEntity player, net.minecraft.world.World world) {
        UUID playerId = player.getUuid();
        Vec3d currentPos = player.getPos();
        long currentTime = world.getTime();

        // 获取上次位置
        Vec3d lastPos = LAST_PLAYER_POS.get(playerId);

        if (lastPos != null) {
            // 计算移动距离和速度
            double distance = currentPos.distanceTo(lastPos);
            double speed = distance; // 每tick的移动距离

            // 更新移动速度缓存
            PLAYER_MOVE_SPEED.put(playerId, speed);

            // 根据移动速度确定更新间隔
            int updateInterval;
            if (speed <= SLOW_MOVE_THRESHOLD) {
                updateInterval = SLOW_UPDATE_INTERVAL; // 慢速或静止：每tick更新
            } else if (speed <= FAST_MOVE_THRESHOLD) {
                updateInterval = NORMAL_UPDATE_INTERVAL; // 正常移动：每2tick更新
            } else {
                updateInterval = FAST_UPDATE_INTERVAL; // 快速移动：每5tick更新，减少粒子密度
            }

            DYNAMIC_UPDATE_INTERVAL.put(playerId, updateInterval);

            // 🔧 调试信息（偶尔输出）- 只在服务器端输出
            if (!world.isClient && currentTime % 100 == 0 && speed > FAST_MOVE_THRESHOLD) {
                SwordAuraLogger.log(SwordAuraLogger.LogLevel.DEBUG, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                        String.format("[%s] 快速移动检测 - 速度:%.3f 更新间隔:%dtick",
                                SwordAuraLogger.getPlayerName(player), speed, updateInterval));
            }
        }

        // 更新位置缓存
        LAST_PLAYER_POS.put(playerId, currentPos);
    }

    /**
     * 🎯 检查是否应该更新粒子（基于动态间隔）
     */
    private static boolean shouldUpdateParticles(UUID playerId, long currentTime) {
        // 获取动态更新间隔（默认为正常间隔）
        int interval = DYNAMIC_UPDATE_INTERVAL.getOrDefault(playerId, NORMAL_UPDATE_INTERVAL);

        // 获取上次更新时间
        Long lastUpdate = LAST_PARTICLE_UPDATE.get(playerId);

        if (lastUpdate == null || (currentTime - lastUpdate) >= interval) {
            // 更新时间戳
            LAST_PARTICLE_UPDATE.put(playerId, currentTime);
            return true;
        }

        return false;
    }

    /**
     * 初始化御剑术系统
     */
    public static void initialize() {
        // 清理所有旧的剑气数据
        cleanupAllData();

        // 初始化事件系统
        initializeEvents();

        // 加载玩家状态
        loadPlayerStates();
        SwordAuraLogger.log(SwordAuraLogger.LogLevel.SUCCESS, SwordAuraLogger.Category.INIT,
                "御剑术系统已初始化，已清理旧数据并加载玩家状态");
    }

    /**
     * 清理所有剑气数据（重启时使用）
     */
    private static void cleanupAllData() {
        FLOATING_SWORDS.clear();
        HIT_EFFECT_SWORDS.clear();
        TARGET_ATTACK_COOLDOWN.clear(); // 清理目标攻击冷却
        MANUAL_ATTACK_TARGETS.clear(); // 清理手动攻击目标
        SWORD_RECOVERY_QUEUE.clear(); // 清理恢复队列
        // 🚀 清理新增的位置缓存
        LAST_PLAYER_POS.clear();
        LAST_PLAYER_YAW.clear();
        LAST_PARTICLE_UPDATE.clear();
        PLAYER_MOVE_SPEED.clear();
        DYNAMIC_UPDATE_INTERVAL.clear();
        // 🔇 清理日志频率控制数据
        LAST_SUPER_LEVEL_LOG.clear();
        GLOBAL_SWORD_COUNTER = 0;
        SwordAuraLogger.cleanup("已清理所有旧的剑气数据（PVP数据由PVP系统管理）", 0);
    }

    /**
     * 悬浮剑实体 - 围绕玩家旋转的剑
     */
    private static class FloatingSword {
        UUID playerId;
        int swordIndex;
        int totalSwords;
        int lifeTick;

        // 🔄 视觉恢复状态 - 不影响攻击逻辑，仅影响渲染
        boolean isVisuallyRecovering = false;
        long visualRecoveryEndTime = 0;

        FloatingSword(UUID playerId, int swordIndex, int totalSwords) {
            this.playerId = playerId;
            this.swordIndex = swordIndex;
            this.totalSwords = totalSwords;
            this.lifeTick = 0;
        }

        /**
         * 设置视觉恢复状态 - 剑逻辑上存在，但视觉上显示为恢复中
         */
        void setVisualRecovery(long endTime) {
            this.isVisuallyRecovering = true;
            this.visualRecoveryEndTime = endTime;
        }

        /**
         * 更新悬浮剑位置并渲染 - 背后剑阵效果
         */
        void update(ServerWorld world, PlayerEntity player) {
            lifeTick++;

            // 🕒 检查视觉恢复状态
            if (isVisuallyRecovering) {
                if (world.getTime() >= visualRecoveryEndTime) {
                    // 恢复完成，清除状态
                    isVisuallyRecovering = false;
                    visualRecoveryEndTime = 0;
                } else {
                    // 仍在恢复中，渲染恢复效果
                    renderRecoveryEffect(world, player);
                    return; // 不渲染正常的悬浮剑
                }
            }

            // 获取玩家朝向（弧度）
            float playerYaw = (float) Math.toRadians(player.getYaw()); // 玩家朝向（弧度）

            // 玩家背后的基础位置
            Vec3d playerPos = player.getPos().add(0, 1.0, 0); // 胸部高度，稍微高一点
            double backDistance = SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE; // 🔧
            // 修正：只设置SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE格距离，避免双重偏移

            // 🔧 修正背后位置计算 - 使用正确的Minecraft坐标系
            // 背后方向 = 玩家朝向 + 180度
            double backAngle = playerYaw + Math.PI; // 正背后180度

            // 🔧 标准化角度到 [0, 2π) 范围
            backAngle = backAngle % (2 * Math.PI);
            if (backAngle < 0)
                backAngle += 2 * Math.PI;

            // 🔧 使用正确的Minecraft方向向量公式
            // 根据Minecraft坐标系：dirX = -sin(θ), dirZ = cos(θ)
            double backX = playerPos.x + backDistance * (-Math.sin(backAngle));
            double backZ = playerPos.z + backDistance * Math.cos(backAngle);

            // 🔍 调试背后方向计算
            // if (swordIndex == 0) {
            // System.out.println("🔧 [背后计算] playerYaw: " + String.format("%.2f°",
            // Math.toDegrees(playerYaw)));
            // System.out.println("🔧 [背后计算] backAngle: " + String.format("%.2f°",
            // Math.toDegrees(backAngle)));
            // System.out.println("🔧 [背后计算] 背后方向向量: " + String.format("(%.3f, %.3f)",
            // -Math.sin(backAngle), Math.cos(backAngle)));
            // System.out.println("🔧 [验证] 实际玩家位置: " + String.format("(%.2f, %.2f, %.2f)",
            // player.getX(), player.getY(), player.getZ()));
            // }

            // 根据剑的索引计算剑阵位置
            Vec3d backPos = new Vec3d(backX, playerPos.y, backZ);
            Vec3d swordPos = calculateSwordArrayPosition(
                    world,
                    backPos,
                    playerYaw,
                    swordIndex,
                    totalSwords,
                    lifeTick);

            // 渲染悬浮剑，透明度根据距离调整
            double distanceToPlayer = swordPos.distanceTo(player.getPos());
            double alpha = Math.max(0.6, 1.0 - (distanceToPlayer - 2.0) * 0.1); // 近处更亮

            // 获取玩家武器类型
            ItemStack weapon = getPlayerWeapon(player);
            WeaponType weaponType = getWeaponType(weapon);

            // 🔧 关键修正：传递圆心位置而不是玩家位置，让剑正确朝向圆心
            Vec3d circleCenter = backPos; // 圆心位置与剑阵位置一致
            renderFloatingSword(world, swordPos, circleCenter, playerYaw, alpha, weaponType);
        }

        /**
         * 渲染恢复效果 - 在视觉恢复期间显示
         */
        void renderRecoveryEffect(ServerWorld world, PlayerEntity player) {
            // 计算恢复进度
            long remainingTime = visualRecoveryEndTime - world.getTime();
            long totalRecoveryTime = SwordAuraConstants.VISUAL_RECOVERY_TIME_TICKS; // 3秒 =
            // SwordAuraConstants.VISUAL_RECOVERY_TIME_TICKS
            // ticks
            double progress = Math.max(0, Math.min(1, (double) remainingTime / totalRecoveryTime));

            // 计算剑应该在的位置
            float playerYaw = (float) Math.toRadians(player.getYaw());
            Vec3d playerPos = player.getPos().add(0, 1.0, 0);
            double backDistance = SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE;
            double backAngle = playerYaw + Math.PI;
            backAngle = backAngle % (2 * Math.PI);
            if (backAngle < 0)
                backAngle += 2 * Math.PI;

            double backX = playerPos.x + backDistance * (-Math.sin(backAngle));
            double backZ = playerPos.z + backDistance * Math.cos(backAngle);
            Vec3d backPos = new Vec3d(backX, playerPos.y, backZ);
            Vec3d swordPos = calculateSwordArrayPosition(world, backPos, playerYaw, swordIndex, totalSwords, lifeTick);

            // 🔄 恢复粒子效果
            if (lifeTick % 3 == 0) { // 每3tick生成一次，避免太密集
                // 🟡 黄色粒子表示恢复进度
                world.spawnParticles(
                        ParticleTypes.ELECTRIC_SPARK,
                        swordPos.x, swordPos.y, swordPos.z,
                        (int) (3 * progress + 1), // 粒子数量随进度变化
                        0.15, 0.15, 0.15, SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);

                // 🟢 绿色粒子表示即将完成
                if (progress < 0.3) {
                    world.spawnParticles(
                            ParticleTypes.HAPPY_VILLAGER,
                            swordPos.x, swordPos.y, swordPos.z,
                            2, 0.1, 0.1, 0.1, 0.01);
                }
            }
        }

        /**
         * 计算剑阵中每把剑的位置 - 垂直圆形剑阵
         */
        private Vec3d calculateSwordArrayPosition(ServerWorld world, Vec3d basePos, float playerYaw, int index,
                                                  int total, int lifeTick) {
            // 🎯 统一的垂直圆形剑阵 - 所有等级都使用相同逻辑，1把剑就在圆圈上的居中位置

            // 🔧 圆心就在basePos位置（已经是玩家背后）
            Vec3d circleCenter = basePos;

            // 🎯 垂直圆形参数
            double baseCircleRadius = 1.0; // 基础圆半径（1格）
            double swordOffset = 1.6; // 剑柄距离基础圆的距离
            double circleRadius = baseCircleRadius + swordOffset; // 总半径 = 1.0 + 1.6 = 2.6格

            // 🔧 每把剑在圆周上的角度
            double angle = index * (2 * Math.PI / total);

            // 🎯 1把剑特殊处理：放在90°位置（垂直上方）而不是0°位置（水平右侧）
            if (total == 1) {
                angle = Math.PI / 2; // 90° = π/2 弧度
            }

            // 🔧 计算玩家背后的方向向量（用于确定右方向）
            double backAngle = playerYaw + Math.PI;
            backAngle = backAngle % (2 * Math.PI);
            if (backAngle < 0)
                backAngle += 2 * Math.PI;
            double backDirX = -Math.sin(backAngle);
            double backDirZ = Math.cos(backAngle);

            // 🔧 在垂直平面内的两个基础向量
            Vec3d upVector = new Vec3d(0, 1, 0); // 向上
            Vec3d rightVector = new Vec3d(-backDirZ, 0, backDirX); // 垂直于背后方向的右方向

            // 🔧 在垂直平面内的圆形分布
            double rightOffset = circleRadius * Math.cos(angle); // 水平偏移
            double upOffset = circleRadius * Math.sin(angle); // 垂直偏移

            Vec3d swordPos = circleCenter
                    .add(rightVector.multiply(rightOffset)) // 水平圆形偏移
                    .add(upVector.multiply(upOffset)); // 垂直圆形偏移

            // 🔧 轻微浮动效果
            double floatOffset = SwordAuraConstants.POSITION_CHANGE_THRESHOLD
                    * Math.sin(lifeTick * SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE
                    + index * SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE);
            swordPos = swordPos.add(0, floatOffset, 0);

            // 🔍 调试信息和圆心标记（只要有剑就显示圆心概念）
            if (index == 0 && total >= 1) {
                // System.out.println("🎯 [统一圆形剑阵] 总剑数: " + total);
                // System.out.println("🎯 [统一圆形剑阵] 圆心位置: " + String.format("(%.2f, %.2f, %.2f)",
                // circleCenter.x, circleCenter.y, circleCenter.z));
                // System.out.println("🎯 [统一圆形剑阵] 基础圆半径: " + baseCircleRadius + "格");
                // System.out.println("🎯 [统一圆形剑阵] 剑距离圆圈: " + swordOffset + "格");
                // System.out.println("🎯 [统一圆形剑阵] 剑距离圆心: " + circleRadius + "格");

                // 🟢 在圆心位置添加粒子标记（明亮的绿色粒子）
                world.spawnParticles(
                        ParticleTypes.HAPPY_VILLAGER, // 明亮的绿色粒子
                        circleCenter.x, circleCenter.y, circleCenter.z,
                        5, // 粒子数量
                        0.1, // X扩散
                        0.1, // Y扩散
                        0.1, // Z扩散
                        0.0 // 额外速度
                );

                // 🔵 在基础圆周上添加蓝色粒子标记（显示1格半径的圆）
                for (int i = 0; i < 8; i++) {
                    double markAngle = i * (2 * Math.PI / 8);
                    double markX = circleCenter.x + rightVector.x * baseCircleRadius * Math.cos(markAngle);
                    double markY = circleCenter.y + upVector.y * baseCircleRadius * Math.sin(markAngle);
                    double markZ = circleCenter.z + rightVector.z * baseCircleRadius * Math.cos(markAngle);

                    world.spawnParticles(
                            ParticleTypes.ENCHANT, // 蓝色附魔粒子
                            markX, markY, markZ,
                            1, // 粒子数量
                            SwordAuraConstants.POSITION_CHANGE_THRESHOLD, // X扩散
                            SwordAuraConstants.POSITION_CHANGE_THRESHOLD, // Y扩散
                            SwordAuraConstants.POSITION_CHANGE_THRESHOLD, // Z扩散
                            0.0 // 额外速度
                    );
                }
            }

            return swordPos;
        }

        /**
         * 高级剑阵 - 4-5剑的复杂阵型
         */
        private Vec3d calculateAdvancedSwordArray(ServerWorld world, Vec3d basePos, float playerYaw, int index,
                                                  int total, int lifeTick) {
            // 🎯 统一使用垂直圆形剑阵 - 与普通悬浮剑使用完全相同的算法
            return calculateSwordArrayPosition(world, basePos, playerYaw, index, total, lifeTick);
        }
    }

    /**
     * 攻击剑实体 - 向目标移动的剑（智能追踪）
     */
    // 💀 已删除AttackingSword类 - 现在使用瞬发攻击系统

    /**
     * 主要处理函数 - 分离服务器端和客户端逻辑
     */
    public static void handleSwordAuraEffect(PlayerEntity player) {
        UUID playerId = player.getUuid();

        // 检查御剑术是否开启
        if (!AURA_ENABLED.getOrDefault(playerId, false)) {
            return; // 御剑术未开启
        }

        // 获取御剑术等级
        int auraLevel = getPlayerSwordAuraLevel(player);
        if (auraLevel <= 0) {
            // 🔧 修复：没有御剑术附魔时，不要强制关闭用户设置的开关状态
            // 只是暂时不显示效果，但保持用户的开关选择
            return; // 没有附魔等级，暂时不显示效果，但不改变开关状态
        }

        if (player.getWorld().isClient) {
            // ===== 客户端逻辑：使用共享渲染器 =====
            // 🎯 使用共享渲染器确保客户端和服务端效果一致
            SwordAuraRenderer.renderSwordAura(player, player.getWorld(), auraLevel);
        } else {
            // ===== 服务器端逻辑：处理攻击和使用共享渲染器 =====
            ServerWorld world = (ServerWorld) player.getWorld();
            long currentTime = world.getTime();

            // 更新击中效果剑（始终更新，不受粒子频率控制影响）
            updateHitEffectSwords(world, playerId);

            // 🆕 更新附近敌人缓存（用于自动攻击）
            updateNearbyEnemiesCache(player);

            // 检测敌人并自动攻击（始终执行，不受粒子频率控制影响）
            checkAutoAttack(world, player, currentTime);

            // 🚀 计算玩家移动速度并确定动态更新间隔
            calculatePlayerMoveSpeedAndInterval(player, world);

            // 🎯 使用共享渲染器进行服务端渲染
            SwordAuraRenderer.renderSwordAura(player, world, auraLevel);
        }
    }

    /**
     * 🚀 智能维护悬浮剑 - 按需更新，避免闪烁
     * 只有在位置、朝向变化或定期刷新时才更新剑阵位置
     */
    public static void maintainFloatingSwordsSmartly(ServerWorld world, PlayerEntity player, int auraLevel,
                                                     long currentTime) {
        UUID playerId = player.getUuid();
        Vec3d currentPos = player.getPos();
        float currentYaw = player.getYaw();

        // 获取缓存的位置信息
        Vec3d lastPos = LAST_PLAYER_POS.get(playerId);
        Float lastYaw = LAST_PLAYER_YAW.get(playerId);
        Long lastUpdate = LAST_PARTICLE_UPDATE.get(playerId);

        // 🔍 检测是否需要更新
        boolean needsUpdate = false;
        String updateReason = "";

        if (lastPos == null || lastYaw == null) {
            needsUpdate = true;
            updateReason = "初次创建";
        } else if (currentPos.distanceTo(lastPos) > SwordAuraConstants.POSITION_CHANGE_THRESHOLD) {
            needsUpdate = true;
            updateReason = String.format("位置变化 %.3fm", currentPos.distanceTo(lastPos));
        } else if (Math.abs(currentYaw - lastYaw) > SwordAuraConstants.YAW_CHANGE_THRESHOLD) {
            needsUpdate = true;
            updateReason = String.format("朝向变化 %.1f度", Math.abs(currentYaw - lastYaw));
        } else if (lastUpdate == null
                || (currentTime - lastUpdate) > SwordAuraConstants.PARTICLE_REFRESH_INTERVAL_TICKS) {
            needsUpdate = true;
            updateReason = "定期刷新";
        }

        // 🎯 只在需要时更新剑阵位置
        if (needsUpdate) {
            // 更新缓存
            LAST_PLAYER_POS.put(playerId, currentPos);
            LAST_PLAYER_YAW.put(playerId, currentYaw);
            LAST_PARTICLE_UPDATE.put(playerId, currentTime);

            // 使用统一日志管理器输出更新信息
            if (updateReason.equals("初次创建")) {
                SwordAuraLogger.initialization(SwordAuraLogger.getPlayerName(player), "悬浮剑初始化");
            }
        }

        // 🌟 每次都更新剑的动画和粒子（但位置只在需要时更新）
        maintainFloatingSwords(world, player, auraLevel);
    }

    /**
     * 维护悬浮剑
     */
    private static void maintainFloatingSwords(ServerWorld world, PlayerEntity player, int auraLevel) {
        UUID playerId = player.getUuid();

        // 🔍 首先检查御剑术是否开启
        if (!AURA_ENABLED.getOrDefault(playerId, false)) {
            // 御剑术未开启，清理所有相关的剑
            List<String> currentSwordKeys = FLOATING_SWORDS.keySet().stream()
                    .filter(key -> key.startsWith(playerId.toString() + "_float_"))
                    .collect(Collectors.toList());

            for (String key : currentSwordKeys) {
                FLOATING_SWORDS.remove(key);
            }

            // 🧹 清理击中效果剑
            HIT_EFFECT_SWORDS.entrySet().removeIf(entry -> entry.getKey().startsWith(playerId.toString() + "_hit_"));

            // 🧹 清理恢复队列
            SWORD_RECOVERY_QUEUE.entrySet()
                    .removeIf(entry -> entry.getKey().startsWith(playerId.toString() + "_recover_"));

            if (!currentSwordKeys.isEmpty()) {
                SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                        String.format("[%s] 御剑术关闭，清理了 %d 把悬浮剑",
                                SwordAuraLogger.getPlayerName(player), currentSwordKeys.size()));
            }

            return; // 御剑术关闭，不需要维护悬浮剑
        }

        // 🎯 新的剑数量计算：最多50把剑
        int swordCount = calculateSwordCount(auraLevel);
        String playerName = SwordAuraLogger.getPlayerName(player);

        // 🌟 显示超级等级信息
        if (auraLevel > SwordAuraConstants.NORMAL_LEVEL_CAP) {
            int superLevels = auraLevel - SwordAuraConstants.NORMAL_LEVEL_CAP;
            float superBonus = calculateSuperLevelBonus(auraLevel);

            // 🔇 频率控制：每5秒最多显示一次超级等级信息，避免日志刷屏
            long currentTime = world.getTime();
            Long lastLogTime = LAST_SUPER_LEVEL_LOG.get(playerId);
            boolean shouldLog = lastLogTime == null || (currentTime - lastLogTime) >= SUPER_LEVEL_LOG_INTERVAL;

            // 🔧 修复：移除错误的模10条件，只使用时间间隔控制
            if (shouldLog) {
                SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                        String.format("[%s] 🌟 超级御剑术 %d级！剑数锁定50把，额外攻击力+%.1f",
                                playerName, auraLevel, superBonus));
                LAST_SUPER_LEVEL_LOG.put(playerId, currentTime);
            }
        }

        // 🗡️ 彻底清理逻辑：先清理所有当前玩家的剑，然后重新创建正确数量的剑
        // 获取当前悬浮剑
        List<String> currentSwordKeys = FLOATING_SWORDS.keySet().stream()
                .filter(key -> key.startsWith(playerId.toString() + "_float_"))
                .collect(Collectors.toList());

        int currentCount = currentSwordKeys.size();

        // 🔄 如果剑数量发生变化，进行彻底清理和重建
        if (currentCount != swordCount) {
            // 🛠️ 新设计：直接重建剑，因为现在用视觉恢复状态控制
            // 清理所有当前玩家的悬浮剑
            for (String key : currentSwordKeys) {
                FLOATING_SWORDS.remove(key);
            }

            // 🧹 清理击中效果剑
            HIT_EFFECT_SWORDS.entrySet().removeIf(entry -> entry.getKey().startsWith(playerId.toString() + "_hit_"));

            // 重新创建正确数量的剑
            for (int i = 0; i < swordCount; i++) {
                String swordKey = playerId.toString() + "_float_" + i;
                FLOATING_SWORDS.put(swordKey, new FloatingSword(playerId, i, swordCount));
            }

            SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                    String.format("[%s] 🗡️ 重建悬浮剑数量: %d → %d把", playerName, currentCount, swordCount));
        }

        // 更新所有悬浮剑
        FLOATING_SWORDS.values().stream()
                .filter(sword -> sword.playerId.equals(playerId))
                .forEach(sword -> sword.update(world, player));
    }

    /**
     * 🔍 检查自动攻击目标 - 使用PVP系统进行检查
     */
    private static void checkAutoAttack(ServerWorld world, PlayerEntity player, long currentTime) {
        // PVE目标检查（对怪物的攻击不受PVP冷却影响）
        List<TargetInfo> allTargets = getTargetsFromCache(player);
        List<TargetInfo> availableTargets = new ArrayList<>();

        for (TargetInfo targetInfo : allTargets) {
            if (targetInfo.entity instanceof PlayerEntity) {
                // PVP目标需要检查冷却
                if (SwordAuraPvPSystem.isPvPAttackAllowed(player, targetInfo.entity, world)) {
                    availableTargets.add(targetInfo);
                }
            } else {
                // 怪物目标直接加入（不受PVP限制）
                availableTargets.add(targetInfo);
            }
        }

        if (!availableTargets.isEmpty()) {
            launchSmartAttack(world, player, availableTargets, false);
        }
    }

    /**
     * 🎯 事件系统初始化
     */
    public static void initializeEvents() {
        SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.INIT,
                "御剑术事件系统已初始化");

        // 玩家攻击事件 - 优先级1
        AttackEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> {
            if (entity instanceof LivingEntity target && player instanceof PlayerEntity) {
                UUID playerId = player.getUuid();
                PLAYER_TARGET_CACHE.put(playerId, target);

                if (AURA_ENABLED.getOrDefault(playerId, false) && !world.isClient) {
                    triggerInstantAttack((ServerWorld) world, (PlayerEntity) player, target, 1);
                }
            }
            return ActionResult.PASS;
        });

        // 玩家受伤事件 - 优先级2
        ServerLivingEntityEvents.ALLOW_DAMAGE.register((entity, source, amount) -> {
            if (entity instanceof ServerPlayerEntity player && source.getAttacker() instanceof LivingEntity attacker) {
                UUID playerId = player.getUuid();

                if (AURA_ENABLED.getOrDefault(playerId, false)) {
                    // 记录攻击者
                    ATTACKING_ENEMIES_CACHE.computeIfAbsent(playerId, k -> new HashSet<>()).add(attacker);
                    triggerInstantAttack(player.getServerWorld(), player, attacker, 2);
                }
            }
            return true;
        });

        // 🆕 玩家死亡事件 - 清理敌对关系
        ServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> {
            if (entity instanceof ServerPlayerEntity deadPlayer) {
                UUID deadPlayerId = deadPlayer.getUuid();
                String deadPlayerName = SwordAuraLogger.getPlayerName(deadPlayer);

                // �� 玩家死亡 - 清理所有相关的敌对关系（委托给PVP系统）
                int clearedHostilities = SwordAuraPvPSystem.clearAllPlayerHostilities(deadPlayerId);
                if (clearedHostilities > 0) {
                    SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.ATTACK,
                            String.format("💀 [%s] 死亡，清理了 %d 个敌对关系 (PVP结束)",
                                    deadPlayerName, clearedHostilities));
                }

                // 🧹 清理玩家数据（保持原有逻辑）
                cleanupPlayerData(deadPlayerId);
            }
        });

        // 🎯 右键空气取消手动攻击事件
        UseItemCallback.EVENT.register((player, world, hand) -> {
            if (player instanceof ServerPlayerEntity && !world.isClient) {
                UUID playerId = player.getUuid();

                // 检查是否开启了御剑术
                if (AURA_ENABLED.getOrDefault(playerId, false)) {
                    // 检查是否有手动攻击目标
                    LivingEntity currentTarget = MANUAL_ATTACK_TARGETS.get(playerId);
                    if (currentTarget != null) {
                        // 取消手动攻击目标
                        MANUAL_ATTACK_TARGETS.remove(playerId);

                        // 发送取消反馈
                        player.sendMessage(Text.literal("§b[御剑术] §7已取消手动攻击目标: §c" +
                                SwordAuraLogger.getEntityName(currentTarget)), true);

                        System.out.println("🎯 [手动攻击] 玩家取消手动攻击目标: " +
                                SwordAuraLogger.getEntityName(currentTarget));
                    }
                }
            }
            return TypedActionResult.pass(player.getStackInHand(hand));
        });
    }

    /**
     * 🚀 立即触发攻击 - 事件驱动
     */
    private static void triggerInstantAttack(ServerWorld world, PlayerEntity player, LivingEntity target,
                                             int priority) {
        UUID playerId = player.getUuid();
        long currentTime = world.getTime();

        // 🎯 手动攻击绕过冷却机制 - 立即执行
        System.out.println("🔧 [SWORD_AURA_DEBUG] 即时攻击触发: " + SwordAuraLogger.getEntityName(target) + " 优先级:" + priority);

        // 🎯 手动攻击绕过目标冷却机制 - 玩家主动操作不应被限制
        String targetKey = playerId.toString() + "_" + target.getUuid().toString();

        // 🔧 只有非手动攻击（优先级>1）才检查目标冷却
        if (priority > 1) {
            Long lastTargetAttack = TARGET_ATTACK_COOLDOWN.get(targetKey);
            if (lastTargetAttack != null && (currentTime - lastTargetAttack) < SwordAuraConstants.ATTACK_COOLDOWN_TICKS) {
                System.out.println("🛡️ [SWORD_AURA_DEBUG] 目标仍在无敌帧中，延迟自动攻击: " + SwordAuraLogger.getEntityName(target));
                return;
            }
        }

        // 🎯 记录手动攻击目标（优先级=1）
        if (priority == 1) {
            MANUAL_ATTACK_TARGETS.put(playerId, target);
            System.out.println("🎯 [手动攻击] 记录手动攻击目标: " + SwordAuraLogger.getEntityName(target));
        }

        // 创建单个目标信息
        TargetInfo targetInfo = new TargetInfo(target, player);
        targetInfo.priority = priority; // 强制设置优先级

        // 🎯 手动攻击使用智能分配，而不是固定数量
        List<TargetInfo> targets = new ArrayList<>();
        targets.add(targetInfo); // 只添加一个目标，让智能分配决定剑数

        // 🔧 只有非手动攻击才设置目标冷却，手动攻击不影响自动攻击
        if (priority > 1) {
            TARGET_ATTACK_COOLDOWN.put(targetKey, currentTime);
        }

        System.out.println("🔧 [SWORD_AURA_DEBUG] 开始执行即时攻击: " + SwordAuraLogger.getEntityName(target));
        launchSmartAttack(world, player, targets, true); // 主动攻击，会建立敌对关系

        // 🔧 正确的优先级文本映射
        String priorityText = (priority == 1) ? "手动攻击目标" :
                (priority == 2) ? "攻击性怪物" : "其他威胁";

        SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.ATTACK,
                String.format("[%s] 即时攻击 - 优先级:%d 目标:%s (%s)",
                        SwordAuraLogger.getPlayerName(player), priority,
                        SwordAuraLogger.getEntityName(target), priorityText));
    }

    /**
     * 检查玩家是否在战斗中 - 🛠️ 修复版：基于实际威胁判定
     */
    private static boolean isPlayerInCombat(PlayerEntity player) {
        UUID playerId = player.getUuid();

        // ⚔️ 检查是否有正在攻击玩家的敌人（真正的威胁）
        Set<LivingEntity> attackingEnemies = ATTACKING_ENEMIES_CACHE.get(playerId);
        if (attackingEnemies != null && !attackingEnemies.isEmpty()) {
            return true;
        }

        // 🛡️ 移除过于严格的"附近有敌人"判定 - 这是bug的根源！
        // 只要附近有敌人就永远不恢复剑，这个逻辑太严格了

        return false; // 没有实际战斗迹象
    }

    /**
     * 📦 更新附近敌人缓存 - 降低扫描频率
     */
    private static void updateNearbyEnemiesCache(PlayerEntity player) {
        UUID playerId = player.getUuid();

        // 只扫描普通威胁，高优先级目标由事件处理
        List<LivingEntity> nearbyEnemies = player.getWorld().getEntitiesByClass(
                LivingEntity.class,
                player.getBoundingBox().expand(SwordAuraConstants.BASE_AUTO_ATTACK_RANGE),
                entity -> entity != player &&
                        entity.isAlive() &&
                        entity.canTakeDamage() &&
                        !ATTACKING_ENEMIES_CACHE.getOrDefault(playerId, Set.of()).contains(entity));
        // 🔧 移除手动攻击目标的排除条件，让自动攻击可以继续攻击手动目标

        NEARBY_ENEMIES_CACHE.put(playerId, new HashSet<>(nearbyEnemies));

        // 📊 使用统一日志管理器输出缓存更新信息
        int lastEnemyCount = LAST_ENEMY_COUNT.getOrDefault(playerId, -1);
        String playerName = SwordAuraLogger.getPlayerName(player);

        if (!nearbyEnemies.isEmpty() && nearbyEnemies.size() != lastEnemyCount) {
            // 找到第一个攻击性怪物作为主要威胁
            String primaryThreat = null;
            for (LivingEntity entity : nearbyEnemies) {
                TargetInfo info = new TargetInfo(entity, player);
                if (info.priority == 1) {
                    primaryThreat = SwordAuraLogger.getEntityName(entity);
                    break;
                }
            }

            SwordAuraLogger.targetDetection(playerName, nearbyEnemies.size(), primaryThreat);
            LAST_ENEMY_COUNT.put(playerId, nearbyEnemies.size());
        } else if (nearbyEnemies.isEmpty() && lastEnemyCount != 0) {
            SwordAuraLogger.cacheUpdate(playerName, "区域清空", -1);
            LAST_ENEMY_COUNT.put(playerId, 0);
        }

        // 清理过期的攻击敌人记录（5秒后清理）
        ATTACKING_ENEMIES_CACHE.computeIfPresent(playerId, (key, enemies) -> {
            enemies.removeIf(enemy -> !enemy.isAlive() ||
                    enemy.getPos().distanceTo(player.getPos()) > SwordAuraConstants.BASE_AUTO_ATTACK_RANGE
                            * SwordAuraConstants.SWORD_HEIGHT_OFFSET);
            return enemies.isEmpty() ? null : enemies;
        });
    }

    /**
     * 📋 从缓存获取目标 - 包含敌对关系玩家的主动检测
     */
    private static List<TargetInfo> getTargetsFromCache(PlayerEntity player) {
        UUID playerId = player.getUuid();
        Set<LivingEntity> nearbyEnemies = NEARBY_ENEMIES_CACHE.get(playerId);

        List<TargetInfo> validTargets = new ArrayList<>();

        // 🎯 第零步：优先处理手动攻击目标
        LivingEntity manualTarget = MANUAL_ATTACK_TARGETS.get(playerId);
        if (manualTarget != null && manualTarget.isAlive() && manualTarget.canTakeDamage()) {
            // 检查手动攻击目标是否还在攻击范围内
            double distance = manualTarget.getPos().distanceTo(player.getPos());
            if (distance <= SwordAuraConstants.BASE_AUTO_ATTACK_RANGE * 1.5) { // 手动攻击目标允许稍远距离
                TargetInfo manualTargetInfo = new TargetInfo(manualTarget, player);
                manualTargetInfo.priority = 1; // 手动攻击目标最高优先级
                manualTargetInfo.assignedSwords = 3; // 分配更多剑数
                validTargets.add(manualTargetInfo);

                System.out.println("🎯 [手动攻击] 优先添加手动攻击目标: " +
                        SwordAuraLogger.getEntityName(manualTarget) + " (距离:" + String.format("%.1f", distance) + ")");
            } else {
                // 手动攻击目标超出范围，清除记录
                MANUAL_ATTACK_TARGETS.remove(playerId);
                System.out.println("🎯 [手动攻击] 手动攻击目标超出范围，清除记录: " +
                        SwordAuraLogger.getEntityName(manualTarget));
            }
        }

        // 🎯 第一步：处理缓存中的附近敌人
        if (nearbyEnemies != null && !nearbyEnemies.isEmpty()) {
            for (LivingEntity entity : nearbyEnemies) {
                if (!entity.isAlive() || !entity.canTakeDamage()) {
                    continue;
                }

                // 🔧 跳过已经作为手动攻击目标添加的实体
                if (manualTarget != null && entity.getUuid().equals(manualTarget.getUuid())) {
                    continue;
                }

                TargetInfo targetInfo = new TargetInfo(entity, player);

                // 🎯 只选择高优先级目标
                if (targetInfo.priority == 1 || targetInfo.priority == 2) {
                    validTargets.add(targetInfo);
                }
                // priority == 999 的目标将被忽略
            }
        }

        // 🔥 第二步：主动检查敌对关系中的玩家（重要修复！）
        long currentTime = player.getWorld().getTime();
        cleanupExpiredHostility(currentTime); // 先清理过期敌对关系

        // 扫描所有在线玩家，检查是否有敌对关系
        if (player.getWorld() instanceof ServerWorld serverWorld) {
            for (ServerPlayerEntity onlinePlayer : serverWorld.getPlayers()) {
                if (onlinePlayer.getUuid().equals(playerId)) {
                    continue; // 跳过自己
                }

                // 检查是否有敌对关系
                boolean hasHostility = SwordAuraPvPSystem.hasActiveHostility(player, onlinePlayer);

                if (hasHostility) {
                    // 检查距离限制（敌对关系允许更远的攻击距离）
                    double distance = onlinePlayer.getPos().distanceTo(player.getPos());
                    double maxHostilityRange = SwordAuraConstants.BASE_AUTO_ATTACK_RANGE * 2.0; // 敌对关系2倍攻击距离

                    if (distance <= maxHostilityRange && onlinePlayer.isAlive() && onlinePlayer.canTakeDamage()) {
                        // 🔧 跳过已经作为手动攻击目标添加的实体
                        if (manualTarget != null && onlinePlayer.getUuid().equals(manualTarget.getUuid())) {
                            continue;
                        }

                        // 检查是否已经在validTargets中
                        boolean alreadyAdded = validTargets.stream()
                                .anyMatch(target -> target.entity.getUuid().equals(onlinePlayer.getUuid()));

                        if (!alreadyAdded) {
                            TargetInfo hostileTarget = new TargetInfo(onlinePlayer, player);
                            if (hostileTarget.priority == 2) { // 确认是敌对关系优先级
                                validTargets.add(hostileTarget);

                                // 🔥 调试日志：敌对关系目标检测
                                SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.ATTACK,
                                        String.format("[%s] 🎯 检测到敌对关系目标: %s (距离:%.1f)",
                                                SwordAuraLogger.getPlayerName(player),
                                                SwordAuraLogger.getPlayerName(onlinePlayer),
                                                distance));
                            }
                        }
                    }
                }
            }
        }

        // 按优先级和威胁等级排序
        validTargets.sort(TargetInfo::compareByPriority);

        // 🎯 分配剑数 - 手动攻击目标优先
        for (int i = 0; i < validTargets.size(); i++) {
            TargetInfo target = validTargets.get(i);
            if (target.assignedSwords == 0) { // 只为还未分配剑数的目标分配
                if (target.priority == 1 && manualTarget != null &&
                        target.entity.getUuid().equals(manualTarget.getUuid())) {
                    // 手动攻击目标已经在添加时分配了3剑，跳过
                    continue;
                } else if (target.priority == 1) {
                    target.assignedSwords = 2; // 攻击性怪物分配2剑
                } else {
                    target.assignedSwords = 1; // 其他目标分配1剑
                }
            }
        }

        // 🧹 清理死亡的手动攻击目标
        if (manualTarget != null && !manualTarget.isAlive()) {
            MANUAL_ATTACK_TARGETS.remove(playerId);
            System.out.println("🎯 [手动攻击] 手动攻击目标已死亡，清除记录: " +
                    SwordAuraLogger.getEntityName(manualTarget));
        }

        return validTargets;
    }

    /**
     * 目标信息类 - 包含预判和优先级
     */
    private static class TargetInfo {
        LivingEntity entity;
        Vec3d predictedPos;
        double threatLevel;
        public int priority; // 1=玩家主动攻击目标, 2=攻击玩家的敌人, 3=其他威胁
        int assignedSwords; // 分配的剑数
        double distance;

        TargetInfo(LivingEntity entity, PlayerEntity player) {
            this.entity = entity;
            this.distance = entity.getPos().distanceTo(player.getPos());

            // 🎯 高级位置预判
            this.predictedPos = calculateAdvancedPrediction(entity, player);

            // 📊 计算威胁等级和优先级
            this.threatLevel = calculateThreatLevel(entity, player);
            this.priority = determineAttackPriority(entity, player);
            this.assignedSwords = 0;
        }

        /**
         * 🧠 高级位置预判 - 考虑双方移动
         */
        private Vec3d calculateAdvancedPrediction(LivingEntity target, PlayerEntity player) {
            Vec3d targetPos = target.getPos().add(0, target.getHeight() / 2, 0);
            Vec3d targetVelocity = target.getVelocity();

            // 计算相对速度和预判时间
            double distanceToTarget = targetPos.distanceTo(player.getPos());
            double swordSpeed = 12.0; // 剑的平均速度
            double baseTime = distanceToTarget / swordSpeed;

            // 考虑目标移动趋势
            double targetSpeed = targetVelocity.length();
            if (targetSpeed > 0.1) {
                // 目标在移动，增加预判时间
                double predictionTime = baseTime + (targetSpeed * SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE);
                Vec3d predictedMove = targetVelocity.multiply(predictionTime);

                // 限制预判距离，避免过度预判
                double maxPrediction = Math.min(distanceToTarget * 0.3,
                        SwordAuraConstants.ELITE_APPLE_CHANCE_MULTIPLIER);
                if (predictedMove.length() > maxPrediction) {
                    predictedMove = predictedMove.normalize().multiply(maxPrediction);
                }

                return targetPos.add(predictedMove);
            }

            return targetPos; // 静止目标直接返回当前位置
        }

        /**
         * 📝 重写的攻击优先级判断 - 按用户需求简化
         */
        private int determineAttackPriority(LivingEntity entity, PlayerEntity player) {
            // 优先级1：攻击性怪物（最高优先级）
            if (isHostileMob(entity)) {
                return 1;
            }

            // 优先级2：真正敌对的PvP目标（需要有敌对关系）
            if (entity instanceof PlayerEntity targetPlayer && hasActiveHostility(player, targetPlayer)) {
                return 2;
            }

            // 优先级3：玩家主动攻击的其他目标
            if (isPlayerAttackingTarget(entity, player)) {
                return 3;
            }

            // 其他情况不攻击
            return 999; // 极低优先级，基本不会被攻击
        }

        /**
         * 🔍 检测是否为攻击性怪物 - 全面检测
         */
        private boolean isHostileMob(LivingEntity entity) {
            EntityType<?> type = entity.getType();

            // 📋 攻击性怪物完整列表
            return type == EntityType.ZOMBIE ||
                    type == EntityType.SKELETON ||
                    type == EntityType.SPIDER ||
                    type == EntityType.CREEPER ||
                    type == EntityType.PILLAGER ||
                    type == EntityType.WARDEN ||
                    type == EntityType.EVOKER ||
                    type == EntityType.VINDICATOR || // 卫道士
                    type == EntityType.ILLUSIONER || // 幻术师
                    type == EntityType.BLAZE ||
                    type == EntityType.GHAST ||
                    type == EntityType.WITHER_SKELETON ||
                    type == EntityType.ENDERMAN ||
                    type == EntityType.PHANTOM ||
                    type == EntityType.RAVAGER ||
                    type == EntityType.ELDER_GUARDIAN ||
                    type == EntityType.GUARDIAN ||
                    type == EntityType.ENDER_DRAGON ||
                    type == EntityType.WITHER ||
                    type == EntityType.WITCH || // 女巫
                    type == EntityType.VEX || // 恼鬼（唤魔者召唤）
                    type == EntityType.ZOMBIFIED_PIGLIN || // 僵尸猪灵
                    type == EntityType.HOGLIN || // 疣猪兽
                    type == EntityType.ZOGLIN || // 僵尸疣猪兽
                    type == EntityType.PIGLIN || // 猪灵（可能攻击性）
                    type == EntityType.PIGLIN_BRUTE || // 猪灵蛮兵
                    type == EntityType.STRIDER || // 炽足兽（在某些情况下）
                    type == EntityType.MAGMA_CUBE || // 岩浆怪
                    type == EntityType.SLIME || // 史莱姆（大型有攻击性）
                    type == EntityType.SILVERFISH || // 蠹虫
                    type == EntityType.SHULKER || // 潜影贝
                    type == EntityType.CAVE_SPIDER || // 洞穴蜘蛛
                    type == EntityType.DROWNED || // 溺尸
                    type == EntityType.HUSK || // 尸壳
                    type == EntityType.STRAY || // 流浪者
                    type == EntityType.BOGGED || // 沼泽骷髅
                    type == EntityType.BREEZE || // 微风
                    type == EntityType.ZOMBIE_VILLAGER; // 僵尸村民
        }

        /**
         * 🔍 检测是否为有效的PvP目标
         */
        private boolean isValidPvPTarget(LivingEntity entity, PlayerEntity attacker) {
            // 只处理玩家目标
            if (!(entity instanceof PlayerEntity targetPlayer)) {
                return false;
            }

            // 🚫 不能攻击自己
            if (targetPlayer.getUuid().equals(attacker.getUuid())) {
                return false;
            }

            // 🚫 创造模式玩家不能被攻击
            if (targetPlayer.isCreative()) {
                return false;
            }

            // 🚫 无敌状态的玩家不能被攻击
            if (targetPlayer.isInvulnerable()) {
                return false;
            }

            // 🚫 同一队伍的玩家不能被攻击（如果有队伍系统）
            if (attacker.getScoreboardTeam() != null &&
                    attacker.getScoreboardTeam().equals(targetPlayer.getScoreboardTeam())) {
                return false;
            }

            // ✅ 通过所有检查的玩家可以被攻击
            return true;
        }

        /**
         * 🔄 修复的玩家攻击目标检测 - 只检测真正的攻击意图
         */
        private boolean isPlayerAttackingTarget(LivingEntity target, PlayerEntity player) {
            // 🎯 对于玩家目标，需要有敌对关系或正在主动攻击
            if (target instanceof PlayerEntity targetPlayer) {
                // 检查是否有敌对关系
                if (hasActiveHostility(player, targetPlayer)) {
                    return true;
                }

                // 检查是否正在主动攻击（玩家正看着目标且距离较近）
                Vec3d playerLook = player.getRotationVector();
                Vec3d toTarget = target.getPos().subtract(player.getPos()).normalize();
                double lookAngle = Math.acos(Math.max(-1.0, Math.min(1.0, playerLook.dotProduct(toTarget))));

                // 如果玩家正看着目标（15度内）且距离很近，认为是主动攻击
                return lookAngle < Math.PI / 12 && distance < 4.0 && isValidPvPTarget(target, player);
            }

            // 🚫 对于非玩家目标，只有攻击性怪物才能成为玩家攻击目标
            if (!isHostileMob(target)) {
                return false;
            }

            // 检查玩家视线方向
            Vec3d playerLook = player.getRotationVector();
            Vec3d toTarget = target.getPos().subtract(player.getPos()).normalize();
            double lookAngle = Math.acos(Math.max(-1.0, Math.min(1.0, playerLook.dotProduct(toTarget))));

            // 如果玩家正看着目标（30度内）且距离较近
            return lookAngle < Math.PI / 6 && distance < 8.0;
        }

        /**
         * 🎯 简化的威胁计算 - 基于新优先级
         */
        private double calculateThreatLevel(LivingEntity entity, PlayerEntity player) {
            double threat = 0.0;

            // 距离因素（越近威胁越高）
            threat += Math.max(0, 1.0 - distance) * 0.1;

            // 生命值因素（残血敌人优先）
            float healthRatio = entity.getHealth() / entity.getMaxHealth();
            if (healthRatio < 0.3)
                threat += 1.0; // 残血优先击杀

            // 基于优先级调整威胁值
            if (priority == 1) {
                threat += SwordAuraConstants.BOSS_APPLE_CHANCE_MULTIPLIER; // 攻击性怪物高威胁
            } else if (priority == 2) {
                threat += SwordAuraConstants.ELITE_APPLE_CHANCE_MULTIPLIER; // 玩家攻击目标中威胁
            }

            return threat;
        }

        boolean isValidTarget() {
            return entity.isAlive() && entity.canTakeDamage();
        }

        /**
         * 优先级比较
         */
        static int compareByPriority(TargetInfo a, TargetInfo b) {
            // 首先按优先级排序
            if (a.priority != b.priority) {
                return Integer.compare(a.priority, b.priority);
            }

            // 相同优先级按威胁等级排序
            if (Math.abs(a.threatLevel - b.threatLevel) > 0.1) {
                return Double.compare(b.threatLevel, a.threatLevel);
            }

            // 最后按距离排序
            return Double.compare(a.distance, b.distance);
        }

        /**
         * 🆕 检查是否有活跃的敌对关系
         */
        private boolean hasActiveHostility(PlayerEntity player1, PlayerEntity player2) {
            return SwordAuraPvPSystem.hasActiveHostility(player1, player2);
        }
    }

    /**
     * 🎯 智能攻击发起系统 - 极简版
     */
    private static void launchSmartAttack(ServerWorld world, PlayerEntity player, List<TargetInfo> targets,
                                          boolean isManualAttack) {
        UUID playerId = player.getUuid();

        // 🎯 获取可用的悬浮剑（正确逻辑）
        List<FloatingSword> availableFloatingSwords = FLOATING_SWORDS.values().stream()
                .filter(sword -> sword.playerId.equals(playerId))
                .collect(Collectors.toList());

        // 如果没有悬浮剑，从剑的索引创建虚拟剑发射位置
        if (availableFloatingSwords.isEmpty()) {
            // 这种情况下，直接使用玩家背后位置计算剑阵
            int auraLevel = getPlayerSwordAuraLevel(player);
            int totalSwords = SwordAuraConstants.calculateSwordCount(auraLevel);

            // 播放攻击音效
            world.playSound(null, player.getX(), player.getY(), player.getZ(),
                    SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP, SoundCategory.PLAYERS,
                    0.8f, 1.2f);

            // 计算背后剑阵基础位置
            Vec3d playerPos = player.getPos().add(0, SwordAuraConstants.SWORD_HEIGHT_OFFSET, 0);
            float playerYaw = (float) Math.toRadians(player.getYaw() + 180);
            double backDistance = SwordAuraConstants.SWORD_ORBIT_DISTANCE;
            double backX = playerPos.x + backDistance * Math.cos(playerYaw);
            double backZ = playerPos.z + backDistance * Math.sin(playerYaw);
            Vec3d baseBackPos = new Vec3d(backX, playerPos.y, backZ);

            // 🚀 智能剑数分配 - 根据敌人威胁等级决定剑数
            int attackCount = calculateSmartSwordAllocation(targets, totalSwords);

            // 📊 输出虚拟剑攻击开始信息
            String playerName = SwordAuraLogger.getPlayerName(player);
            SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.ATTACK,
                    String.format("[%s] 虚拟剑攻击开始 - 无悬浮剑 目标数:%d 实际攻击:%d",
                            playerName, targets.size(), attackCount));

            // 🎯 智能分配虚拟剑攻击 - 根据每个目标分配的剑数进行攻击
            int virtualSwordIndex = 0;
            for (TargetInfo targetInfo : targets) {
                if (virtualSwordIndex >= attackCount) {
                    break; // 剑已用完
                }

                int swordsForThisTarget = targetInfo.assignedSwords;

                // 📊 输出目标攻击开始信息
                EntityType<?> type = targetInfo.entity.getType();
                String entityTypeName = type.toString().replace("minecraft:", "");
                float maxHealth = targetInfo.entity.getMaxHealth();
                float currentHealth = targetInfo.entity.getHealth();
                String healthCategory = getHealthCategory(maxHealth);
                SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.ATTACK,
                        String.format("[%s] 🎯 虚拟剑对 %s 分配 %d 把剑 (血量:%.0f/%.0f %s)",
                                playerName, entityTypeName, swordsForThisTarget, currentHealth, maxHealth,
                                healthCategory));

                // 为这个目标分配指定数量的虚拟剑
                for (int s = 0; s < swordsForThisTarget && virtualSwordIndex < attackCount; s++) {
                    // 🛠️ 修复：虚拟剑攻击时不调用包含圆心渲染的位置计算
                    Vec3d startPos = calculateSimpleAttackPosition(baseBackPos, playerYaw, virtualSwordIndex,
                            totalSwords);

                    // 📊 输出虚拟剑使用详情
                    SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                            String.format("[%s] 虚拟剑%d 瞬间攻击 -> %s (第%d把)",
                                    playerName, virtualSwordIndex, entityTypeName, s + 1));

                    // 🚀 瞬发攻击：直接造成伤害并创建击中效果
                    dealDamage(world, targetInfo.entity, virtualSwordIndex, player, isManualAttack);

                    // 🎯 创建击中效果剑（动态限制，根据御剑术等级调整）
                    int playerAuraLevel = getPlayerSwordAuraLevel(player);
                    int maxHitEffects = Math.min(playerAuraLevel * 2, SwordAuraConstants.MAX_HIT_EFFECTS_PER_PLAYER); // 每级允许2个击中效果

                    long currentHitEffectCount = HIT_EFFECT_SWORDS.entrySet().stream()
                            .filter(entry -> entry.getKey().startsWith(playerId.toString() + "_hit_"))
                            .count();

                    if (currentHitEffectCount < maxHitEffects) {
                        String hitEffectKey = playerId.toString() + "_hit_" + virtualSwordIndex;
                        ItemStack weapon = getPlayerWeapon(player);
                        WeaponType weaponType = getWeaponType(weapon);
                        HIT_EFFECT_SWORDS.put(hitEffectKey,
                                new HitEffectSword(playerId, virtualSwordIndex, targetInfo.entity, weaponType));

                        // 🔍 调试信息：击中效果剑创建
                        System.out.println("✨ [击中效果] 创建击中效果剑" + virtualSwordIndex + " | 当前/最大: "
                                + (currentHitEffectCount + 1) + "/" + maxHitEffects + " | 御剑术等级: " + playerAuraLevel);
                    } else {
                        // 🔍 调试信息：击中效果限制
                        System.out.println("⚠️ [击中效果] 击中效果剑被限制 | 当前/最大: " + currentHitEffectCount + "/" + maxHitEffects
                                + " | 御剑术等级: " + playerAuraLevel);
                    }

                    // 📊 统一命中率统计 - 缓存攻击100%命中
                    String priorityText = (targetInfo.priority == 1) ? "手动攻击目标" :
                            (targetInfo.priority == 2) ? "攻击性怪物" : "其他威胁";
                    recordAttackAndHit(playerId, virtualSwordIndex, targetInfo.entity, true, "智能虚拟攻击-" + priorityText);

                    virtualSwordIndex++;
                }
            }

            // 📊 输出虚拟剑攻击完成总结
            SwordAuraLogger.log(SwordAuraLogger.LogLevel.SUCCESS, SwordAuraLogger.Category.ATTACK,
                    String.format("[%s] 虚拟剑攻击完成 - 使用剑数:%d (无悬浮剑消耗)",
                            playerName, virtualSwordIndex));
            return;
        }

        // 原有逻辑：有悬浮剑时使用悬浮剑发射
        // 播放攻击音效
        world.playSound(null, player.getX(), player.getY(), player.getZ(),
                SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP, SoundCategory.PLAYERS,
                0.8f, 1.2f);

        // 计算背后剑阵基础位置
        Vec3d playerPos = player.getPos().add(0, SwordAuraConstants.SWORD_HEIGHT_OFFSET, 0);
        float playerYaw = (float) Math.toRadians(player.getYaw() + 180);
        double backDistance = SwordAuraConstants.SWORD_ORBIT_DISTANCE;
        double backX = playerPos.x + backDistance * Math.cos(playerYaw);
        double backZ = playerPos.z + backDistance * Math.sin(playerYaw);
        Vec3d baseBackPos = new Vec3d(backX, playerPos.y, backZ);

        // 发射剑攻击 - 智能分配剑数
        int maxPossible = Math.min(availableFloatingSwords.size(),
                calculateSmartSwordAllocation(targets, availableFloatingSwords.size()));
        int attackCount = maxPossible;
        List<Integer> usedSwordIndices = new ArrayList<>();

        // 📊 输出悬浮剑攻击开始信息
        String playerName = SwordAuraLogger.getPlayerName(player);
        SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.ATTACK,
                String.format("[%s] 悬浮剑攻击开始 - 可用剑数:%d 目标数:%d 实际攻击:%d",
                        playerName, availableFloatingSwords.size(), targets.size(), attackCount));

        // 🎯 智能分配攻击 - 根据每个目标分配的剑数进行攻击
        int currentSwordIndex = 0;
        for (TargetInfo targetInfo : targets) {
            if (currentSwordIndex >= availableFloatingSwords.size()) {
                break; // 剑已用完
            }

            int swordsForThisTarget = targetInfo.assignedSwords;

            // 📊 输出目标攻击开始信息
            EntityType<?> type = targetInfo.entity.getType();
            String entityTypeName = type.toString().replace("minecraft:", "");
            float maxHealth = targetInfo.entity.getMaxHealth();
            float currentHealth = targetInfo.entity.getHealth();
            String healthCategory = getHealthCategory(maxHealth);
            SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.ATTACK,
                    String.format("[%s] 🎯 对 %s 分配 %d 把剑 (血量:%.0f/%.0f %s)",
                            playerName, entityTypeName, swordsForThisTarget, currentHealth, maxHealth, healthCategory));

            // 为这个目标分配指定数量的剑
            for (int s = 0; s < swordsForThisTarget && currentSwordIndex < availableFloatingSwords.size(); s++) {
                FloatingSword floatingSword = availableFloatingSwords.get(currentSwordIndex);

                // 🛠️ 修复：攻击时不调用包含圆心渲染的剑阵计算，直接使用简单位置计算
                Vec3d startPos = calculateSimpleAttackPosition(baseBackPos, playerYaw, floatingSword.swordIndex,
                        floatingSword.totalSwords);

                // 📊 输出悬浮剑使用详情
                SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                        String.format("[%s] 悬浮剑%d 转为攻击模式 -> %s (第%d把)",
                                playerName, floatingSword.swordIndex, entityTypeName, s + 1));

                // 🚀 瞬发攻击：直接造成伤害并创建击中效果
                dealDamage(world, targetInfo.entity, floatingSword.swordIndex, player, isManualAttack);

                // 🎯 创建击中效果剑（动态限制，根据御剑术等级调整）
                int playerAuraLevel = getPlayerSwordAuraLevel(player);
                int maxHitEffects = Math.min(playerAuraLevel * 2, SwordAuraConstants.MAX_HIT_EFFECTS_PER_PLAYER); // 每级允许2个击中效果

                long currentHitEffectCount = HIT_EFFECT_SWORDS.entrySet().stream()
                        .filter(entry -> entry.getKey().startsWith(playerId.toString() + "_hit_"))
                        .count();

                if (currentHitEffectCount < maxHitEffects) {
                    String hitEffectKey = playerId.toString() + "_hit_" + floatingSword.swordIndex;
                    ItemStack weapon = getPlayerWeapon(player);
                    WeaponType weaponType = getWeaponType(weapon);
                    HIT_EFFECT_SWORDS.put(hitEffectKey,
                            new HitEffectSword(playerId, floatingSword.swordIndex, targetInfo.entity, weaponType));

                    // 🔍 调试信息：悬浮剑击中效果创建
                    System.out.println("✨ [悬浮剑击中效果] 创建击中效果剑" + floatingSword.swordIndex + " | 当前/最大: "
                            + (currentHitEffectCount + 1) + "/" + maxHitEffects + " | 御剑术等级: " + playerAuraLevel);
                } else {
                    // 🔍 调试信息：悬浮剑击中效果限制
                    System.out.println("⚠️ [悬浮剑击中效果] 击中效果剑被限制 | 当前/最大: " + currentHitEffectCount + "/" + maxHitEffects
                            + " | 御剑术等级: " + playerAuraLevel);
                }

                // 📊 统一命中率统计 - 缓存攻击100%命中
                String priorityText = (targetInfo.priority == 1) ? "手动攻击目标" :
                        (targetInfo.priority == 2) ? "攻击性怪物" : "其他威胁";
                recordAttackAndHit(playerId, floatingSword.swordIndex, targetInfo.entity, true, "智能攻击-" + priorityText);

                usedSwordIndices.add(floatingSword.swordIndex);
                currentSwordIndex++;
            }
        }

        // ✅ 新设计：逻辑上立即恢复，视觉上3秒恢复
        // 步骤1：设置视觉恢复状态（不移除剑，保持攻击能力）
        long recoverTime = world.getTime() + SwordAuraConstants.VISUAL_RECOVERY_TIME_TICKS; // SwordAuraConstants.VISUAL_RECOVERY_TIME_TICKS
        // ticks = 3秒视觉恢复
        for (int swordIndex : usedSwordIndices) {
            String floatKey = playerId.toString() + "_float_" + swordIndex;
            FloatingSword sword = FLOATING_SWORDS.get(floatKey);
            if (sword != null) {
                sword.setVisualRecovery(recoverTime);
            }
        }

        // 步骤2：清理旧的恢复队列系统（不再需要）
        // 移除旧的延迟恢复逻辑

        // 📊 输出攻击完成总结（视觉恢复模式）
        int totalSwords = (int) FLOATING_SWORDS.values().stream()
                .filter(s -> s.playerId.equals(playerId))
                .count();
        int recoveringSwords = (int) FLOATING_SWORDS.values().stream()
                .filter(s -> s.playerId.equals(playerId) && s.isVisuallyRecovering)
                .count();
        SwordAuraLogger.log(SwordAuraLogger.LogLevel.SUCCESS, SwordAuraLogger.Category.ATTACK,
                String.format("[%s] 悬浮剑攻击完成 - 总剑数:%d 恢复中:%d 可攻击:%d",
                        playerName, totalSwords, recoveringSwords, totalSwords - recoveringSwords));
    }

    /**
     * 📊 获取血量分类标签
     */
    private static String getHealthCategory(float maxHealth) {
        if (maxHealth >= SwordAuraConstants.SUPER_BOSS_HEALTH_THRESHOLD) {
            return "超级Boss";
        } else if (maxHealth >= SwordAuraConstants.LARGE_BOSS_HEALTH_THRESHOLD) {
            return "大型Boss";
        } else if (maxHealth >= SwordAuraConstants.MEDIUM_BOSS_HEALTH_THRESHOLD) {
            return "中型Boss";
        } else if (maxHealth >= SwordAuraConstants.ELITE_MOB_HEALTH_THRESHOLD) {
            return "精英怪物";
        } else if (maxHealth >= SwordAuraConstants.ENHANCED_MOB_HEALTH_THRESHOLD) {
            return "强化怪物";
        } else {
            return "普通怪物";
        }
    }

    /**
     * 🎯 智能剑数分配 - 根据怪物血量通用分配（支持所有mod的怪物）
     */
    private static int calculateSmartSwordAllocation(List<TargetInfo> targets, int totalSwords) {
        if (targets.isEmpty())
            return 0;

        int allocatedSwords = 0;

        for (TargetInfo target : targets) {
            int swordsForThisTarget = 1; // 默认每个敌人分配1把剑

            // 🩺 基于血量的智能分配（适用于所有mod的怪物）
            float maxHealth = target.entity.getMaxHealth();
            float currentHealth = target.entity.getHealth();
            float healthRatio = currentHealth / maxHealth;

            // 📊 根据最大血量判断威胁等级（基于御剑术等级比例的智能分配）
            if (maxHealth >= SwordAuraConstants.SUPER_BOSS_HEALTH_THRESHOLD) {
                // 超级Boss（1000+血量）：分配75-100%的剑
                swordsForThisTarget = Math.max(1, (int) Math.ceil(totalSwords * 0.75));
                if (maxHealth >= SwordAuraConstants.ULTRA_BOSS_HEALTH_THRESHOLD) {
                    swordsForThisTarget = totalSwords; // 超超级Boss用所有剑
                }
            } else if (maxHealth >= SwordAuraConstants.LARGE_BOSS_HEALTH_THRESHOLD) {
                // 大型Boss（500-999血量）：分配50-75%的剑
                double ratio = SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE
                        + (maxHealth - SwordAuraConstants.LARGE_BOSS_HEALTH_THRESHOLD)
                        / SwordAuraConstants.LARGE_BOSS_HEALTH_THRESHOLD * 0.25; // 50%-75%
                swordsForThisTarget = Math.max(1, (int) Math.ceil(totalSwords * ratio));
            } else if (maxHealth >= SwordAuraConstants.MEDIUM_BOSS_HEALTH_THRESHOLD) {
                // 中型Boss（200-499血量）：分配30-50%的剑
                double ratio = 0.3 + (maxHealth - SwordAuraConstants.MEDIUM_BOSS_HEALTH_THRESHOLD) / 300.0f * 0.2; // 30%-50%
                swordsForThisTarget = Math.max(1, (int) Math.ceil(totalSwords * ratio));
            } else if (maxHealth >= SwordAuraConstants.ELITE_MOB_HEALTH_THRESHOLD) {
                // 精英怪物（100-199血量）：分配20-30%的剑
                double ratio = 0.2 + (maxHealth - SwordAuraConstants.ELITE_MOB_HEALTH_THRESHOLD)
                        / SwordAuraConstants.ELITE_MOB_HEALTH_THRESHOLD * 0.1; // 20%-30%
                swordsForThisTarget = Math.max(1, (int) Math.ceil(totalSwords * ratio));
            } else if (maxHealth >= SwordAuraConstants.ENHANCED_MOB_HEALTH_THRESHOLD) {
                // 强化怪物（50-99血量）：分配10-20%的剑
                double ratio = 0.1 + (maxHealth - SwordAuraConstants.ENHANCED_MOB_HEALTH_THRESHOLD)
                        / SwordAuraConstants.ENHANCED_MOB_HEALTH_THRESHOLD * 0.1; // 10%-20%
                swordsForThisTarget = Math.max(1, (int) Math.ceil(totalSwords * ratio));
            } else {
                // 普通怪物（<50血量）：分配5-10%的剑，最少1把
                double ratio = Math.max(SwordAuraConstants.POSITION_CHANGE_THRESHOLD,
                        SwordAuraConstants.POSITION_CHANGE_THRESHOLD
                                + maxHealth / SwordAuraConstants.ENHANCED_MOB_HEALTH_THRESHOLD
                                * SwordAuraConstants.POSITION_CHANGE_THRESHOLD); // 5%-10%
                swordsForThisTarget = Math.max(1, (int) Math.ceil(totalSwords * ratio));
            }

            // 🩸 残血敌人：减少剑数（避免浪费）
            if (healthRatio < 0.15f && swordsForThisTarget > 1) {
                swordsForThisTarget = 1; // 残血只用一把剑
            } else if (healthRatio < 0.3f && swordsForThisTarget > 2) {
                swordsForThisTarget = Math.max(1, swordsForThisTarget - 1); // 低血量适当减剑
            }

            // 📊 威胁等级微调（距离、攻击性等因素）
            if (target.threatLevel > 1.0) {
                swordsForThisTarget = Math.min(swordsForThisTarget + 1, totalSwords);
            }

            // 🎯 优先级调整
            if (target.priority == 1) {
                // 主动攻击的目标：可能增加1把剑
                if (maxHealth >= SwordAuraConstants.ELITE_MOB_HEALTH_THRESHOLD && swordsForThisTarget < totalSwords) {
                    swordsForThisTarget = Math.min(swordsForThisTarget + 1, totalSwords);
                }
            }

            // 累计分配剑数，但不超过总剑数
            allocatedSwords += swordsForThisTarget;
            target.assignedSwords = swordsForThisTarget; // 记录分配的剑数

            if (allocatedSwords >= totalSwords) {
                allocatedSwords = totalSwords;
                break; // 剑已用完
            }
        }

        return Math.min(allocatedSwords, totalSwords);
    }

    /**
     * 安排悬浮剑延迟恢复
     */
    private static void scheduleFloatingSwordRecovery(UUID playerId, List<Integer> swordIndices, long recoverTime) {
        for (int swordIndex : swordIndices) {
            String recoveryKey = playerId.toString() + "_recover_" + swordIndex;
            SWORD_RECOVERY_QUEUE.put(recoveryKey, recoverTime);
        }

        String playerName = SwordAuraLogger.getPlayerName(null);
        SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                String.format("已安排 %d 把剑在 %d tick后恢复", swordIndices.size(), recoverTime));
    }

    /**
     * 处理延迟恢复的悬浮剑
     */
    private static void processDelayedSwordRecovery(ServerWorld world, UUID playerId, int totalSwords) {
        long currentTime = world.getTime();
        List<String> completedRecoveries = new ArrayList<>();

        // 检查所有恢复队列中的剑
        for (Map.Entry<String, Long> entry : SWORD_RECOVERY_QUEUE.entrySet()) {
            String recoveryKey = entry.getKey();
            long recoverTime = entry.getValue();

            // 检查是否属于当前玩家且时间已到
            if (recoveryKey.startsWith(playerId.toString() + "_recover_") && currentTime >= recoverTime) {
                // 解析剑索引
                String[] parts = recoveryKey.split("_");
                if (parts.length == 3) {
                    try {
                        int swordIndex = Integer.parseInt(parts[2]);

                        // 恢复悬浮剑
                        String swordKey = playerId.toString() + "_float_" + swordIndex;
                        FLOATING_SWORDS.put(swordKey, new FloatingSword(playerId, swordIndex, totalSwords));

                        // 记录完成的恢复
                        completedRecoveries.add(recoveryKey);

                        String playerName = SwordAuraLogger.getPlayerName(null);
                        SwordAuraLogger.log(SwordAuraLogger.LogLevel.SUCCESS, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                                String.format("[%s] 🔄 悬浮剑%d 已恢复", playerName, swordIndex));

                    } catch (NumberFormatException e) {
                        // 索引解析失败，跳过
                        completedRecoveries.add(recoveryKey);
                    }
                }
            }
        }

        // 清理已完成的恢复
        for (String key : completedRecoveries) {
            SWORD_RECOVERY_QUEUE.remove(key);
        }
    }

    /**
     * 渲染恢复中剑的粒子效果
     */
    private static void renderRecoveringEffects(ServerWorld world, PlayerEntity player) {
        UUID playerId = player.getUuid();
        String playerIdStr = playerId.toString();
        long currentTime = world.getTime();

        // 检查恢复队列中属于此玩家的剑
        for (Map.Entry<String, Long> entry : SWORD_RECOVERY_QUEUE.entrySet()) {
            String recoveryKey = entry.getKey();
            long recoverTime = entry.getValue();

            if (recoveryKey.startsWith(playerIdStr + "_recover_")) {
                // 解析剑索引
                String[] parts = recoveryKey.split("_");
                if (parts.length == 3) {
                    try {
                        int swordIndex = Integer.parseInt(parts[2]);

                        // 计算恢复进度 (0.0 到 1.0)
                        long totalRecoveryTime = SwordAuraConstants.VISUAL_RECOVERY_TIME_TICKS; // 3秒恢复时间
                        long elapsed = currentTime - (recoverTime - totalRecoveryTime);
                        double progress = Math.max(0.0, Math.min(1.0, (double) elapsed / totalRecoveryTime));

                        // 在玩家背后对应位置显示恢复粒子
                        Vec3d playerPos = player.getPos();
                        float playerYaw = player.getYaw();
                        Vec3d baseBackPos = playerPos.add(
                                -SwordAuraConstants.SWORD_HEIGHT_OFFSET * Math.sin(Math.toRadians(playerYaw)),
                                1.8,
                                -SwordAuraConstants.SWORD_HEIGHT_OFFSET * Math.cos(Math.toRadians(playerYaw)));

                        // 计算剑的恢复位置
                        Vec3d recoverPos = calculateBackSwordPosition(baseBackPos, playerYaw, swordIndex, 1);

                        // 恢复粒子效果：逐渐增强
                        int particleCount = (int) (progress * 8) + 1;
                        double particleSpeed = progress * 0.1;

                        // 🔄 恢复粒子：从暗到亮
                        world.spawnParticles(
                                ParticleTypes.ENCHANT,
                                recoverPos.x, recoverPos.y, recoverPos.z,
                                particleCount,
                                0.1 * progress,
                                0.1 * progress,
                                0.1 * progress,
                                particleSpeed);

                        // 🌟 恢复进度提示（90%以上显示强光）
                        if (progress > 0.9) {
                            world.spawnParticles(
                                    ParticleTypes.TOTEM_OF_UNDYING,
                                    recoverPos.x, recoverPos.y, recoverPos.z,
                                    3,
                                    SwordAuraConstants.POSITION_CHANGE_THRESHOLD,
                                    SwordAuraConstants.POSITION_CHANGE_THRESHOLD,
                                    SwordAuraConstants.POSITION_CHANGE_THRESHOLD,
                                    SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);
                        }

                    } catch (NumberFormatException e) {
                        // 索引解析失败，跳过
                    }
                }
            }
        }
    }

    /**
     * 计算背后剑阵中指定索引剑的位置
     */
    private static Vec3d calculateBackSwordPosition(Vec3d baseBackPos, float playerYaw, int swordIndex,
                                                    int totalSwords) {
        // 🗡️ 背后垂直圆形剑阵 - 与悬浮剑保持一致
        double backDistance = 1.2; // 圆心距离玩家背后的距离（稍远一些，确保完全在背后）
        double circleRadius = 0.4; // 圆形半径（更紧凑，确保不会伸到前面）

        // ✅ 使用Sample.java中的正确背后定位逻辑
        double backAngle = playerYaw + Math.PI; // 正背后180度
        double backDirX = Math.cos(backAngle);
        double backDirZ = Math.sin(backAngle);

        // 计算圆心位置：玩家背后backDistance距离，与玩家眼部同高
        Vec3d circleCenter = baseBackPos.add(
                backDirX * backDistance,
                SwordAuraConstants.SWORD_HEIGHT_OFFSET, // 眼部高度
                backDirZ * backDistance);

        if (totalSwords == 1) {
            // 单剑：直接位于圆心
            return circleCenter;
        } else {
            // 多剑：在圆周上等间距分布
            double angleStep = (2 * Math.PI) / totalSwords;
            double swordAngle = angleStep * swordIndex;

            // 计算在圆周上的位置
            double offsetX = Math.cos(swordAngle) * circleRadius;
            double offsetZ = Math.sin(swordAngle) * circleRadius;

            return circleCenter.add(offsetX, 0, offsetZ);
        }
    }

    /**
     * 计算攻击位置 - 不包含圆心渲染逻辑的简化版本
     */
    private static Vec3d calculateSimpleAttackPosition(Vec3d baseBackPos, float playerYaw, int swordIndex,
                                                       int totalSwords) {
        // 🗡️ 基础位置计算 - 不包含调试和圆心渲染
        double backDistance = 1.2;
        double circleRadius = 0.4;

        // 背后方向向量
        double backAngle = playerYaw + Math.PI;
        double backDirX = Math.cos(backAngle);
        double backDirZ = Math.sin(backAngle);

        // 圆心位置
        Vec3d circleCenter = baseBackPos.add(
                backDirX * backDistance,
                SwordAuraConstants.SWORD_HEIGHT_OFFSET,
                backDirZ * backDistance);

        if (totalSwords == 1) {
            return circleCenter;
        } else {
            // 多剑圆周分布
            double angleStep = (2 * Math.PI) / totalSwords;
            double swordAngle = angleStep * swordIndex;

            double offsetX = Math.cos(swordAngle) * circleRadius;
            double offsetZ = Math.sin(swordAngle) * circleRadius;

            return circleCenter.add(offsetX, 0, offsetZ);
        }
    }

    /**
     * 击中效果剑实体 - 显示击中特效
     */
    private static class HitEffectSword {
        UUID playerId;
        int swordIndex;
        Vec3d targetPos;
        LivingEntity target;
        WeaponType weaponType;
        int lifeTick;

        HitEffectSword(UUID playerId, int swordIndex, LivingEntity target, WeaponType weaponType) {
            this.playerId = playerId;
            this.swordIndex = swordIndex;
            this.target = target;
            this.weaponType = weaponType;
            this.targetPos = target.getPos().add(0, target.getHeight() / 2, 0);
            this.lifeTick = 0;
        }

        /**
         * 更新击中效果剑 - 仅显示效果，不移动
         */
        boolean update(ServerWorld world) {
            lifeTick++;

            // 🎯 击中效果持续30tick后消失（SwordAuraConstants.SWORD_HEIGHT_OFFSET秒，更清晰可见，适配高等级御剑术）
            // 💀 重要修复：即使目标死亡，击中效果也要持续显示，让玩家看到攻击效果
            if (lifeTick > 30) {
                return false; // 效果结束
            }

            // 更新目标位置（如果目标还活着就跟随移动，死亡后保持在死亡位置）
            if (target.isAlive()) {
                this.targetPos = target.getPos().add(0, target.getHeight() / 2, 0);
            }
            // 目标死亡后，targetPos保持不变，击中效果在死亡位置继续显示

            // 渲染击中剑效果
            renderHitEffectSword(world, targetPos, target, weaponType);

            return true; // 继续显示效果
        }
    }

    // 💀 已删除SmartAttackingSword类 - 现在使用瞬发攻击系统

    /**
     * 💀 已删除废弃的launchAttack方法 - 有错误的立即恢复逻辑，现在统一使用launchSmartAttack方法
     */

    /**
     * 更新击中效果剑
     */
    private static void updateHitEffectSwords(ServerWorld world, UUID playerId) {
        Iterator<Map.Entry<String, HitEffectSword>> iterator = HIT_EFFECT_SWORDS.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry<String, HitEffectSword> entry = iterator.next();
            HitEffectSword hitSword = entry.getValue();

            if (!hitSword.playerId.equals(playerId))
                continue;

            if (!hitSword.update(world)) {
                // 击中效果结束，移除
                iterator.remove();
            }
        }
    }

    /**
     * 关闭御剑术
     */
    private static void disableAura(UUID playerId) {
        AURA_ENABLED.put(playerId, false);

        // 🧹 清理所有相关的剑 - 更彻底的清理
        List<String> removedSwords = new ArrayList<>();

        // 清理悬浮剑
        FLOATING_SWORDS.entrySet().removeIf(entry -> {
            if (entry.getKey().startsWith(playerId.toString() + "_float_")) {
                removedSwords.add(entry.getKey());
                return true;
            }
            return false;
        });

        // 清理击中效果剑
        HIT_EFFECT_SWORDS.entrySet().removeIf(entry -> entry.getKey().startsWith(playerId.toString() + "_hit_"));

        // 清理恢复队列
        SWORD_RECOVERY_QUEUE.entrySet().removeIf(entry -> entry.getKey().startsWith(playerId.toString() + "_recover_"));

        // 清理位置缓存
        LAST_PLAYER_POS.remove(playerId);
        LAST_PLAYER_YAW.remove(playerId);
        LAST_PARTICLE_UPDATE.remove(playerId);
        PLAYER_MOVE_SPEED.remove(playerId);
        DYNAMIC_UPDATE_INTERVAL.remove(playerId);

        // 清理其他缓存
        NEARBY_ENEMIES_CACHE.remove(playerId);
        ATTACKING_ENEMIES_CACHE.remove(playerId);
        PLAYER_TARGET_CACHE.remove(playerId);
        CACHE_UPDATE_TIME.remove(playerId);

        // 清理统计数据
        HIT_COUNT.remove(playerId);
        TOTAL_ATTACKS.remove(playerId);
        LAST_STATS_TIME.remove(playerId);

        // 清理状态记录
        LAST_ENEMY_COUNT.remove(playerId);
        LAST_SWORD_STATUS_LOG.remove(playerId);
        LAST_SWORD_COUNT.remove(playerId);
        LAST_SUPER_LEVEL_LOG.remove(playerId);

        if (!removedSwords.isEmpty()) {
            SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                    String.format("🔒 御剑术关闭，清理了 %d 把悬浮剑", removedSwords.size()));
        }
    }

    /**
     * 渲染悬浮剑 - 根据武器类型显示不同粒子效果
     */
    private static void renderFloatingSword(ServerWorld world, Vec3d pos, Vec3d playerPos, float playerYaw,
                                            double alpha, WeaponType weaponType) {
        double length = getWeaponLength(weaponType);

        // 🗡️ 计算剑的朝向：剑柄朝向圆心，剑尖朝外，并向玩家背后方向倾斜10°
        Vec3d fromPlayer = pos.subtract(playerPos);
        Vec3d swordAxis;

        if (fromPlayer.length() < 0.1) {
            // 如果剑就在玩家位置（异常情况），默认朝向北方
            swordAxis = new Vec3d(0, 0, -1);
        } else {
            // 🎯 基础剑轴：从玩家指向剑（剑尖朝外，剑柄朝向玩家/圆心）
            Vec3d baseSwordAxis = fromPlayer.normalize();

            // 🎯 计算玩家背后的方向向量（使用玩家朝向信息）
            double backAngle = playerYaw + Math.PI;
            backAngle = backAngle % (2 * Math.PI);
            if (backAngle < 0)
                backAngle += 2 * Math.PI;

            // 🎯 玩家背后的方向向量
            Vec3d backDirection = new Vec3d(-Math.sin(backAngle), 0, Math.cos(backAngle));
            backDirection = backDirection.normalize();

            // 🎯 计算倾斜角度：10° = 0.174532925 弧度
            double tiltAngle = Math.toRadians(SwordAuraConstants.BOSS_APPLE_CHANCE_MULTIPLIER);
            double cosAngle = Math.cos(tiltAngle); // ≈ 0.985
            double sinAngle = Math.sin(tiltAngle); // ≈ 0.174

            // 🎯 创建倾斜后的剑轴：基础方向 * cos(10°) + 背后方向 * sin(10°)
            swordAxis = baseSwordAxis.multiply(cosAngle).add(backDirection.multiply(sinAngle));
            swordAxis = swordAxis.normalize();

            // 🔍 调试信息（只在特定时刻输出，避免刷屏）
            // if (world.getTime() % 20 == 0) { // 每秒输出一次
            // System.out.println("🎯 [剑倾斜] 基础剑轴: " + String.format("(%.3f, %.3f, %.3f)",
            // baseSwordAxis.x, baseSwordAxis.y, baseSwordAxis.z));
            // System.out.println("🎯 [剑倾斜] 背后方向: " + String.format("(%.3f, %.3f, %.3f)",
            // backDirection.x, backDirection.y, backDirection.z));
            // System.out.println("🎯 [剑倾斜] 倾斜剑轴: " + String.format("(%.3f, %.3f, %.3f)",
            // swordAxis.x, swordAxis.y, swordAxis.z));
            // }
        }

        // 计算武器的各部分位置：剑柄朝外，剑尖朝向圆心
        Vec3d handle = pos.add(swordAxis.multiply(length / 2)); // 剑柄：朝外
        Vec3d guard = pos.add(swordAxis.multiply(length / 8)); // 护手：稍微朝外
        Vec3d tip = pos.add(swordAxis.multiply(-length / 2)); // 剑尖：朝向圆心

        // 计算侧向量
        Vec3d up = new Vec3d(0, 1, 0);
        Vec3d sideVector = swordAxis.crossProduct(up).normalize().multiply(getWeaponWidth(weaponType));

        // 根据武器类型渲染不同形状和粒子
        switch (weaponType) {
            case SWORD -> renderSwordShape(world, pos, tip, guard, handle, sideVector, alpha);
            case AXE -> renderAxeShape(world, pos, tip, guard, handle, sideVector, alpha);
            case ROD -> renderRodShape(world, pos, tip, guard, handle, sideVector, alpha);
            case ARROW -> renderArrowShape(world, pos, tip, guard, handle, sideVector, alpha);
            case WAND -> renderWandShape(world, pos, tip, guard, handle, sideVector, alpha);
            case TRIDENT -> renderTridentShape(world, pos, tip, guard, handle, sideVector, alpha);
            case BOW -> renderBowShape(world, pos, tip, guard, handle, sideVector, alpha);
            case STICK -> renderStickShape(world, pos, tip, guard, handle, sideVector, alpha);
            case TOOL -> renderToolShape(world, pos, tip, guard, handle, sideVector, alpha);
            default -> renderDefaultShape(world, pos, tip, guard, handle, sideVector, alpha);
        }

        // 🔇 注释掉频繁的粒子效果日志
        // System.out.println("🎨 [悬浮剑] " + weaponType.displayName + "类型粒子效果");
    }

    private static double getWeaponLength(WeaponType type) {
        return switch (type) {
            case SWORD, TRIDENT -> 2.0;
            case AXE, TOOL -> 1.6;
            case ROD -> 2.5;
            case ARROW -> 1.2;
            case WAND -> 1.4;
            case BOW -> 1.8;
            case STICK -> SwordAuraConstants.SWORD_HEIGHT_OFFSET;
            default -> 1.8;
        };
    }

    private static double getWeaponWidth(WeaponType type) {
        return switch (type) {
            case AXE -> 0.2;
            case SWORD -> 0.1;
            case ROD, STICK, ARROW -> SwordAuraConstants.POSITION_CHANGE_THRESHOLD;
            case WAND -> 0.08;
            case TRIDENT -> 0.15;
            case BOW -> 0.12;
            case TOOL -> 0.12;
            default -> 0.1;
        };
    }

    // 🗡️ 剑形状 - 经典附魔粒子（优化版：更持久的粒子）
    private static void renderSwordShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                         Vec3d sideVector, double alpha) {
        // 🌟 增加粒子密度和持续时间
        for (int i = 0; i <= 15; i++) {
            double t = (double) i / 15;
            Vec3d bladeCenter = guard.add(tip.subtract(guard).multiply(t));

            // 更密集的粒子生成
            world.spawnParticles(ParticleTypes.ENCHANT,
                    bladeCenter.x, bladeCenter.y, bladeCenter.z,
                    2, 0.002, 0.002, 0.002, 0); // 增加数量，减少扩散
        }
        // 剑尖特效 - 更明显
        world.spawnParticles(ParticleTypes.ENCHANT, tip.x, tip.y, tip.z, 4, 0.005, 0.005, 0.005,
                SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);

        // 🔥 护手光环效果
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.1;
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.ENCHANT,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    // 🪓 斧头形状 - 暴击粒子（借鉴剑的8点光环效果）
    private static void renderAxeShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                       Vec3d sideVector, double alpha) {
        // 斧头刃部 - 更宽更短
        for (int i = 0; i <= 12; i++) {
            double t = (double) i / 12;
            Vec3d bladeCenter = guard.add(tip.subtract(guard).multiply(t));
            double bladeWidth = (1.0 - t * 0.3) * 0.25; // 斧头刃部更宽

            Vec3d leftEdge = bladeCenter.add(sideVector.multiply(bladeWidth));
            Vec3d rightEdge = bladeCenter.subtract(sideVector.multiply(bladeWidth));

            world.spawnParticles(ParticleTypes.CRIT,
                    leftEdge.x, leftEdge.y, leftEdge.z, 2, 0.005, 0.005, 0.005, 0);
            world.spawnParticles(ParticleTypes.CRIT,
                    rightEdge.x, rightEdge.y, rightEdge.z, 2, 0.005, 0.005, 0.005, 0);
        }
        // 斧头柄特效
        world.spawnParticles(ParticleTypes.CRIT, handle.x, handle.y, handle.z, 3,
                SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE, SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE,
                SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE, SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);

        // 🔥 护手光环效果 - 借鉴剑的8点圆形
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.12; // 斧头护手稍大
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.CRIT,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    // 🎣 钓竿形状 - 钓鱼粒子（借鉴剑的8点光环效果）
    private static void renderRodShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                       Vec3d sideVector, double alpha) {
        // 细长的竿
        for (int i = 0; i <= 18; i++) {
            double t = (double) i / 18;
            Vec3d rodPos = handle.add(tip.subtract(handle).multiply(t));
            world.spawnParticles(ParticleTypes.FISHING,
                    rodPos.x, rodPos.y, rodPos.z, 2, 0.002, 0.002, 0.002, 0);
        }
        // 钓线效果
        world.spawnParticles(ParticleTypes.FISHING, tip.x, tip.y - SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE, tip.z,
                4, 0.08, 0.08, 0.08, SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);

        // 🔥 护手光环效果 - 借鉴剑的8点圆形
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.08; // 钓竿护手较小
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.FISHING,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    // 🏹 箭矢形状 - 末地烛粒子（借鉴剑的8点光环效果）
    private static void renderArrowShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                         Vec3d sideVector, double alpha) {
        // 箭身
        for (int i = 0; i <= 12; i++) {
            double t = (double) i / 12;
            Vec3d arrowPos = handle.add(tip.subtract(handle).multiply(t));
            world.spawnParticles(ParticleTypes.END_ROD,
                    arrowPos.x, arrowPos.y, arrowPos.z, 2, 0.002, 0.002, 0.002, 0);
        }
        // 箭头
        world.spawnParticles(ParticleTypes.END_ROD, tip.x, tip.y, tip.z, 4, 0.01, 0.01, 0.01,
                SwordAuraConstants.POSITION_CHANGE_THRESHOLD);
        // 箭羽
        world.spawnParticles(ParticleTypes.END_ROD, handle.x, handle.y, handle.z, 3, 0.03, 0.03, 0.03,
                SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);

        // 🔥 护手光环效果 - 借鉴剑的8点圆形
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.06; // 箭的护手更小
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.END_ROD,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    // 🪄 魔杖形状 - 女巫粒子（借鉴剑的8点光环效果）
    private static void renderWandShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                        Vec3d sideVector, double alpha) {
        // 杖身
        for (int i = 0; i <= 14; i++) {
            double t = (double) i / 14;
            Vec3d wandPos = handle.add(tip.subtract(handle).multiply(t));
            world.spawnParticles(ParticleTypes.WITCH,
                    wandPos.x, wandPos.y, wandPos.z, 2, 0.005, 0.005, 0.005, 0);
        }
        // 魔法宝石
        world.spawnParticles(ParticleTypes.WITCH, tip.x, tip.y, tip.z, 6, 0.03, 0.03, 0.03, 0.1);

        // 🔥 护手光环效果 - 借鉴剑的8点圆形
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.09; // 魔杖护手适中
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.WITCH,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    // 🔱 三叉戟形状 - 气泡粒子（借鉴剑的8点光环效果）
    private static void renderTridentShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                           Vec3d sideVector, double alpha) {
        // 戟柄
        for (int i = 0; i <= 15; i++) {
            double t = (double) i / 15;
            Vec3d shaftPos = handle.add(guard.subtract(handle).multiply(t));
            world.spawnParticles(ParticleTypes.BUBBLE_POP,
                    shaftPos.x, shaftPos.y, shaftPos.z, 2, 0.002, 0.002, 0.002, 0);
        }
        // 三叉戟头
        world.spawnParticles(ParticleTypes.BUBBLE_POP, tip.x, tip.y, tip.z, 3, 0.005, 0.005, 0.005,
                SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);
        Vec3d leftProng = tip.add(sideVector.multiply(0.1));
        Vec3d rightProng = tip.subtract(sideVector.multiply(0.1));
        world.spawnParticles(ParticleTypes.BUBBLE_POP, leftProng.x, leftProng.y, leftProng.z, 2, 0.005, 0.005, 0.005,
                SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);
        world.spawnParticles(ParticleTypes.BUBBLE_POP, rightProng.x, rightProng.y, rightProng.z, 2, 0.005, 0.005, 0.005,
                SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);

        // 🔥 护手光环效果 - 借鉴剑的8点圆形
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.11; // 三叉戟护手较大
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.BUBBLE_POP,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    // 🏹 弓形状 - 堆肥桶粒子（借鉴剑的8点光环效果）
    private static void renderBowShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                       Vec3d sideVector, double alpha) {
        // 弓臂
        for (int i = 0; i <= 14; i++) {
            double t = (double) i / 14;
            Vec3d bowPos = handle.add(tip.subtract(handle).multiply(t));
            double curve = Math.sin(t * Math.PI) * 0.2;
            Vec3d curvedPos = bowPos.add(sideVector.multiply(curve));
            world.spawnParticles(ParticleTypes.COMPOSTER,
                    curvedPos.x, curvedPos.y, curvedPos.z, 2, 0.005, 0.005, 0.005, 0);
        }
        // 弓弦
        world.spawnParticles(ParticleTypes.COMPOSTER, handle.x, handle.y, handle.z, 2, 0.01, 0.01, 0.01, 0);
        world.spawnParticles(ParticleTypes.COMPOSTER, tip.x, tip.y, tip.z, 2, 0.01, 0.01, 0.01, 0);

        // 🔥 护手光环效果 - 借鉴剑的8点圆形
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.10; // 弓的护手适中
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.COMPOSTER,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    // 🪵 木棍形状 - 灰烬粒子（借鉴剑的8点光环效果）
    private static void renderStickShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                         Vec3d sideVector, double alpha) {
        // 木棍主体
        for (int i = 0; i <= 15; i++) {
            double t = (double) i / 15;
            Vec3d stickPos = handle.add(tip.subtract(handle).multiply(t));
            world.spawnParticles(ParticleTypes.ASH,
                    stickPos.x, stickPos.y, stickPos.z, 2, 0.002, 0.002, 0.002, 0);
        }

        // 🔥 护手光环效果 - 借鉴剑的8点圆形
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.07; // 木棍护手较小
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.ASH,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    // 🔨 工具形状 - 烟雾粒子（稳定持续，不闪烁）
    private static void renderToolShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                        Vec3d sideVector, double alpha) {
        // 工具主体 - 使用稳定的烟雾粒子
        for (int i = 0; i <= 12; i++) {
            double t = (double) i / 12;
            Vec3d toolPos = handle.add(tip.subtract(handle).multiply(t));
            world.spawnParticles(ParticleTypes.SMOKE,
                    toolPos.x, toolPos.y, toolPos.z, 2, 0.002, 0.002, 0.002, 0);
        }

        // 🔥 护手光环效果 - 借鉴剑的8点圆形，使用稳定粒子
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.11; // 工具护手较大
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.SMOKE,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }

        // ⚡ 工具尖端特效 - 金属光泽
        world.spawnParticles(ParticleTypes.ELECTRIC_SPARK,
                tip.x, tip.y, tip.z, 2, 0.005, 0.005, 0.005, 0.01);
    }

    // ❓ 默认形状 - 烟雾粒子（借鉴剑的8点光环效果）
    private static void renderDefaultShape(ServerWorld world, Vec3d pos, Vec3d tip, Vec3d guard, Vec3d handle,
                                           Vec3d sideVector, double alpha) {
        // 默认主体
        for (int i = 0; i <= 15; i++) {
            double t = (double) i / 15;
            Vec3d defaultPos = handle.add(tip.subtract(handle).multiply(t));
            world.spawnParticles(ParticleTypes.SMOKE,
                    defaultPos.x, defaultPos.y, defaultPos.z, 2, 0.002, 0.002, 0.002, 0);
        }

        // 🔥 护手光环效果 - 借鉴剑的8点圆形
        for (int i = 0; i < 8; i++) {
            double angle = (i / 8.0) * Math.PI * 2;
            double radius = 0.08; // 默认护手适中
            Vec3d guardPos = guard.add(
                    Math.cos(angle) * radius,
                    0,
                    Math.sin(angle) * radius);
            world.spawnParticles(ParticleTypes.SMOKE,
                    guardPos.x, guardPos.y, guardPos.z,
                    1, 0.001, 0.001, 0.001, 0);
        }
    }

    /**
     * 渲染攻击剑 - 增强追踪视觉效果
     */
    // 💀 已删除renderAttackingSword方法 - 瞬发攻击不需要飞行剑渲染

    /**
     * 渲染击中效果剑 - 直接出现在目标身上
     */
    private static void renderHitEffectSword(ServerWorld world, Vec3d targetPos, LivingEntity target,
                                             WeaponType weaponType) {
        double length = getWeaponLength(weaponType);

        // 剑垂直插在目标身上，剑尖向上
        Vec3d swordAxis = new Vec3d(0, 1, 0); // 垂直向上

        // 计算剑的各部分位置
        Vec3d tip = targetPos.add(0, length / 2, 0);
        Vec3d guard = targetPos.add(0, -length / 8, 0);
        Vec3d handle = targetPos.add(0, -length / 2, 0);

        // 计算侧向量
        Vec3d sideVector = new Vec3d(1, 0, 0).multiply(getWeaponWidth(weaponType));

        // === 使用统一的击中效果系统 ===
        HitEffect.renderHitEffect(world, targetPos, tip, guard, handle, sideVector, weaponType);

        // === 通用击中冲击波 ===
        // world.spawnParticles(ParticleTypes.EXPLOSION,
        //         targetPos.x, targetPos.y, targetPos.z,
        //         3, 0.1, 0.1, 0.1, SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE);
    }

    /**
     * 📊 统一的命中率统计方法
     */
    private static void recordAttackAndHit(UUID playerId, int swordIndex, LivingEntity target, boolean isHit,
                                           String attackType) {
        // 记录攻击次数
        TOTAL_ATTACKS.put(playerId, TOTAL_ATTACKS.getOrDefault(playerId, 0) + 1);

        // 如果击中，记录击中次数
        if (isHit) {
            HIT_COUNT.put(playerId, HIT_COUNT.getOrDefault(playerId, 0) + 1);
        }

        // 输出实时命中率
        int hits = HIT_COUNT.get(playerId);
        int total = TOTAL_ATTACKS.get(playerId);
        double hitRate = (double) hits / total * 100;

        String result = isHit ? "击中" : "失败";
        String targetName = target != null ? target.getName().getString() : "未知目标";

        System.out.println("📊 [" + attackType + "] 剑" + swordIndex + " " + result + " " + targetName +
                " | 命中率: " + hits + "/" + total + " (" + String.format("%.1f", hitRate) + "%)");
    }

    /**
     * 📊 只记录攻击次数（用于开始攻击时）
     */
    private static void recordAttackStart(UUID playerId, int swordIndex, LivingEntity target, String attackType) {
        TOTAL_ATTACKS.put(playerId, TOTAL_ATTACKS.getOrDefault(playerId, 0) + 1);
        System.out.println("⚔️ [" + attackType + "] 剑" + swordIndex + " 开始攻击 " + target.getName().getString());
    }

    /**
     * 📊 只记录击中（用于击中时）
     */
    private static void recordHit(UUID playerId, int swordIndex, LivingEntity target, String attackType) {
        HIT_COUNT.put(playerId, HIT_COUNT.getOrDefault(playerId, 0) + 1);

        // 🔇 减少命中率日志频率 - 仅每10次攻击或整数关键点输出
        int hits = HIT_COUNT.get(playerId);
        int total = TOTAL_ATTACKS.get(playerId);
        double hitRate = (double) hits / total * 100;

        if (total % 10 == 0 || hits % 10 == 0 || total <= 5) {
            System.out.println("✅ [" + attackType + "] 剑" + swordIndex + " 击中 " + target.getName().getString() +
                    " | 📊 命中率: " + hits + "/" + total + " (" + String.format("%.1f", hitRate) + "%)");
        }
    }

    /**
     * 📊 记录失败（用于超时时）
     */
    private static void recordMiss(UUID playerId, int swordIndex, LivingEntity target, String attackType,
                                   String reason) {
        // 不增加击中次数，但输出命中率
        int hits = HIT_COUNT.get(playerId);
        int total = TOTAL_ATTACKS.get(playerId);
        double hitRate = total > 0 ? (double) hits / total * 100 : 0;

        // 🔇 减少失败日志频率 - 仅在重要失败时输出
        String targetName = target != null ? target.getName().getString() : "未知目标";
        if (!reason.equals("攻击被格挡或无效") && total % 10 == 0) {
            System.out.println("❌ [" + attackType + "] 剑" + swordIndex + " 失败: " + reason + " (目标: " + targetName +
                    ") | 📊 命中率: " + hits + "/" + total + " (" + String.format("%.1f", hitRate) + "%)");
        }
    }

    /**
     * 造成伤害 - 完整支持武器附魔效果，并收集经验和掉落物
     */
    private static void dealDamage(ServerWorld world, LivingEntity target, int swordIndex, PlayerEntity player,
                                   boolean isManualAttack) {
        // 🛡️ PvP保护检查 - 防止无限循环攻击
        if (!SwordAuraPvPSystem.isPvPAttackAllowed(player, target, world)) {
            // 攻击被PvP保护机制阻止
            if (target instanceof PlayerEntity targetPlayer) {
                String playerName = SwordAuraLogger.getPlayerName(player);
                String targetName = SwordAuraLogger.getPlayerName(targetPlayer);
                SwordAuraLogger.log(SwordAuraLogger.LogLevel.WARN, SwordAuraLogger.Category.DAMAGE,
                        String.format("[%s] PvP攻击被保护机制阻止 -> %s (冷却/次数限制)",
                                playerName, targetName));
            }
            return;
        }

        // 获取玩家的武器
        ItemStack weapon = getPlayerWeapon(player);
        if (weapon.isEmpty()) {
            System.out.println("⚠️ [剑" + swordIndex + "] 玩家没有武器，跳过攻击");
            return;
        }

        // 🗡️ 创建玩家攻击伤害源（而不是魔法伤害源）
        DamageSource damageSource = world.getDamageSources().playerAttack(player);

        // ⚔️ 计算完整的武器伤害（基础攻击力 + 锋利附魔）
        float baseDamage = calculateWeaponDamage(weapon, player);
        float bonusDamage = swordIndex * 1.5f; // 御剑术加成：每把剑+SwordAuraConstants.SWORD_HEIGHT_OFFSET攻击力
        float totalDamage = baseDamage + bonusDamage;

        // 💀 记录攻击前的目标状态
        float targetHealthBefore = target.getHealth();
        Vec3d targetPos = target.getPos();
        boolean willDie = targetHealthBefore <= totalDamage;

        // 💀 执行攻击（会自动触发所有武器附魔效果）
        boolean damageDealt = target.damage(damageSource, totalDamage);

        if (damageDealt) {
            // 🔄 建立PVP敌对关系（只在主动攻击时，避免自动攻击重新建立敌对关系）
            if (target instanceof PlayerEntity targetPlayer && isManualAttack) {
                SwordAuraPvPSystem.establishHostility(player, targetPlayer, world);

                String playerName = SwordAuraLogger.getPlayerName(player);
                String targetName = SwordAuraLogger.getPlayerName(targetPlayer);
                SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.ATTACK,
                        String.format("🔥 [%s] 主动攻击建立敌对关系 -> %s (60秒)",
                                playerName, targetName));
            }

            // 🎵 击中音效（防止高等级御剑术音效过于密集）
            UUID playerId = player.getUuid();
            long currentTime = world.getTime();
            Long lastSoundTime = LAST_HIT_SOUND_TIME.get(playerId);

            // 🔇 音效冷却检查：每0.25秒最多播放一次击中音效
            if (lastSoundTime == null || (currentTime - lastSoundTime) >= SwordAuraConstants.HIT_SOUND_COOLDOWN_TICKS) {
                world.playSound(null, target.getX(), target.getY(), target.getZ(),
                        SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP, SoundCategory.PLAYERS,
                        0.9f, 1.2f + (swordIndex * 0.1f)); // 每把剑音调略有不同
                LAST_HIT_SOUND_TIME.put(playerId, currentTime);
            }

            // 💰 检查目标是否死亡，如果是则收集经验和掉落物
            if (willDie && target.isDead()) {
                collectExperienceAndLoot(world, target, player, targetPos);
            }

            // 📊 使用统一日志系统输出攻击结果
            String playerName = SwordAuraLogger.getPlayerName(player);
            String targetName = SwordAuraLogger.getEntityName(target);
            String damageDetails = String.format("%.1f点伤害 (基础:%.1f + 御剑术:%.1f)",
                    totalDamage, baseDamage, bonusDamage);
            String attackType = isManualAttack ? "主动" : "自动";

            SwordAuraLogger.log(SwordAuraLogger.LogLevel.COMBAT, SwordAuraLogger.Category.DAMAGE,
                    String.format("[%s] %s攻击剑%d 击中 %s 造成 %s",
                            playerName, attackType, swordIndex, targetName, damageDetails));
        } else {
            // 📊 输出格挡信息
            String playerName = SwordAuraLogger.getPlayerName(player);
            String targetName = SwordAuraLogger.getEntityName(target);
            String attackType = isManualAttack ? "主动" : "自动";
            SwordAuraLogger.log(SwordAuraLogger.LogLevel.WARN, SwordAuraLogger.Category.DAMAGE,
                    String.format("[%s] %s攻击剑%d 攻击 %s 被格挡或无效",
                            playerName, attackType, swordIndex, targetName));
        }
    }

    /**
     * 收集经验和掉落物到玩家位置
     */
    private static void collectExperienceAndLoot(ServerWorld world, LivingEntity target, PlayerEntity player,
                                                 Vec3d deathPos) {
        try {
            // 🎯 获取玩家位置
            Vec3d playerPos = player.getPos();

            // 💎 收集经验值
            collectExperienceOrbs(world, deathPos, playerPos, player);

            // 📦 收集掉落物
            collectDroppedItems(world, deathPos, playerPos, player);

            // 🍎 几率获得附魔金苹果
            trySpawnEnchantedGoldenApple(world, target, player, playerPos);

            // 🎵 播放收集音效
            world.playSound(null, playerPos.x, playerPos.y, playerPos.z,
                    SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.PLAYERS,
                    0.8f, 1.0f + (float) (Math.random() * 0.4 - 0.2));

            // 📊 日志记录
            String playerName = player.getName().getString();
            String targetName = target.getName().getString();
            System.out.println("💰 [" + playerName + "] 御剑术击杀 " + targetName + "，经验和掉落物已收集到玩家位置");

        } catch (Exception e) {
            System.err.println("⚠️ [收集物品] 收集经验和掉落物时发生错误: " + e.getMessage());
        }
    }

    /**
     * 几率获得附魔金苹果
     */
    private static void trySpawnEnchantedGoldenApple(ServerWorld world, LivingEntity target, PlayerEntity player,
                                                     Vec3d playerPos) {
        try {
            // 🎯 基础几率：2%
            double baseChance = SwordAuraConstants.BASE_ENCHANTED_APPLE_CHANCE;

            // 🎯 根据怪物类型调整几率
            double finalChance = calculateEnchantedAppleChance(target, baseChance);

            // 🎲 几率判定
            if (Math.random() < finalChance) {
                // 🍎 创建附魔金苹果
                ItemStack enchantedApple = new ItemStack(Items.ENCHANTED_GOLDEN_APPLE, 1);
                // 创建下界合金碎片
                ItemStack netheriteScrap = new ItemStack(Items.NETHERITE_SCRAP, 1);

                // 🎯 生成到玩家位置
                ItemEntity appleEntity = new ItemEntity(world,
                        playerPos.x, playerPos.y + 1.0, playerPos.z,
                        enchantedApple);
                ItemEntity scrapEntity = new ItemEntity(world,
                        playerPos.x, playerPos.y + 1.0, playerPos.z,
                        netheriteScrap);

                // 🎨 设置特殊效果
                appleEntity.setPickupDelay(0); // 立即可拾取
                appleEntity.setVelocity(0, 0.2, 0); // 轻微上抛

                scrapEntity.setPickupDelay(0); // 立即可拾取
                scrapEntity.setVelocity(0, 0.2, 0); // 轻微上抛

                // 🌟 生成实体到世界
                world.spawnEntity(appleEntity);
                world.spawnEntity(scrapEntity);

                // 🎵 播放特殊音效 - 附魔台音效，更符合魔法物品主题
                world.playSound(null, playerPos.x, playerPos.y, playerPos.z,
                        SoundEvents.BLOCK_ENCHANTMENT_TABLE_USE, SoundCategory.PLAYERS,
                        1.0f, 1.2f);

                // ✨ 生成华丽的粒子效果
                spawnEnchantedAppleParticles(world, playerPos);

                // 📊 日志记录
                String playerName = player.getName().getString();
                String targetName = target.getName().getString();
                // 🍎 输出附魔金苹果获得信息
                System.out.println("🍎 [" + playerName + "] 御剑术击杀 " + targetName + " 获得附魔金苹果！(几率: "
                        + String.format("%.2f%%", finalChance * 100) + ")");
                // 输出下界合金碎片获得信息
                System.out.println(" [" + playerName + "] 御剑术击杀 " + targetName + " 获得下界合金碎片！(几率: "
                        + String.format("%.2f%%", finalChance * 100) + ")");

                // 🏆 向玩家发送消息
                if (player instanceof ServerPlayerEntity serverPlayer) {
                    serverPlayer.sendMessage(
                            Text.literal("§6§l✨ 御剑术击杀获得 §e§l附魔金苹果 §6§l✨")
                                    .append(Text.literal(
                                            "§f (几率: §a" + String.format("%.2f%%", finalChance * 100) + "§f)")),
                            false);
                    serverPlayer.sendMessage(
                            Text.literal("§6§l✨ 御剑术击杀获得 §e§l下界合金碎片 §6§l✨")
                                    .append(Text.literal(
                                            "§f (几率: §a" + String.format("%.2f%%", finalChance * 100) + "§f)")),
                            false);
                }
            }

        } catch (Exception e) {
            System.err.println("⚠️ [附魔金苹果] 生成附魔金苹果时发生错误: " + e.getMessage());
            System.err.println("⚠️ [下界合金碎片] 生成下界合金碎片时发生错误: " + e.getMessage());
        }
    }

    /**
     * 计算附魔金苹果掉落几率
     */
    private static double calculateEnchantedAppleChance(LivingEntity target, double baseChance) {
        double chance = baseChance;

        // 🎯 根据怪物类型调整几率
        String mobName = target.getType().toString().toLowerCase();

        // 🏆 Boss级怪物 - 更高几率
        if (mobName.contains("wither") || mobName.contains("dragon") || mobName.contains("elder_guardian")) {
            chance *= SwordAuraConstants.BOSS_APPLE_CHANCE_MULTIPLIER; // Boss怪物10倍几率 (20%)
        }
        // 🔥 强力怪物 - 高几率
        else if (mobName.contains("blaze") || mobName.contains("ghast") || mobName.contains("shulker") ||
                mobName.contains("guardian") || mobName.contains("warden")) {
            chance *= SwordAuraConstants.ELITE_APPLE_CHANCE_MULTIPLIER; // 强力怪物5倍几率 (10%)
        }
        // ⚔️ 精英怪物 - 中等几率
        else if (mobName.contains("vindicator") || mobName.contains("evoker") || mobName.contains("ravager") ||
                mobName.contains("piglin_brute") || mobName.contains("hoglin")) {
            chance *= SwordAuraConstants.STRONG_APPLE_CHANCE_MULTIPLIER; // 精英怪物3倍几率 (6%)
        }
        // 🧟 普通敌对怪物 - 标准几率
        else if (mobName.contains("zombie") || mobName.contains("skeleton") || mobName.contains("creeper") ||
                mobName.contains("spider") || mobName.contains("enderman") || mobName.contains("witch")) {
            chance *= 1.0; // 普通怪物标准几率 (2%)
        }
        // 🐷 被动/中性怪物 - 低几率
        else {
            chance *= SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE; // 被动怪物减半几率 (1%)
        }

        // 🎯 根据怪物血量调整几率
        float maxHealth = target.getMaxHealth();
        if (maxHealth >= 100) {
            chance *= 2.0; // 高血量怪物双倍几率
        } else if (maxHealth >= 50) {
            chance *= SwordAuraConstants.SWORD_HEIGHT_OFFSET; // 中血量怪物SwordAuraConstants.SWORD_HEIGHT_OFFSET倍几率
        }

        // 🎯 限制最大几率为50%
        return Math.min(chance, SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE);
    }

    /**
     * 生成附魔金苹果的华丽粒子效果
     */
    private static void spawnEnchantedAppleParticles(ServerWorld world, Vec3d pos) {
        // 🌟 金色粒子环绕效果
        for (int i = 0; i < 20; i++) {
            double angle = (i / 20.0) * Math.PI * 2;
            double radius = 1.0;
            double x = pos.x + Math.cos(angle) * radius;
            double z = pos.z + Math.sin(angle) * radius;

            // 金色附魔粒子
            world.spawnParticles(ParticleTypes.ENCHANT,
                    x, pos.y + 1.0, z,
                    2, 0.1, 0.1, 0.1, 0.1);
        }

        // ✨ 向上喷射的金色粒子
        world.spawnParticles(ParticleTypes.ENCHANT,
                pos.x, pos.y + 1.0, pos.z,
                15, 0.3, SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE, 0.3, 0.2);

        // 🎆 爆炸效果
        world.spawnParticles(ParticleTypes.EXPLOSION,
                pos.x, pos.y + 1.0, pos.z,
                1, 0, 0, 0, 0);

        // 🌈 彩色粒子
        world.spawnParticles(ParticleTypes.HAPPY_VILLAGER,
                pos.x, pos.y + 1.0, pos.z,
                10, SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE, SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE,
                SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE, 0.1);
    }

    /**
     * 收集经验球到玩家位置
     */
    private static void collectExperienceOrbs(ServerWorld world, Vec3d deathPos, Vec3d playerPos, PlayerEntity player) {
        // 🎯 搜索死亡位置附近的经验球
        double searchRadius = 8.0; // 搜索半径8格
        List<ExperienceOrbEntity> nearbyOrbs = world.getEntitiesByClass(
                ExperienceOrbEntity.class,
                new Box(deathPos.x - searchRadius, deathPos.y - searchRadius, deathPos.z - searchRadius,
                        deathPos.x + searchRadius, deathPos.y + searchRadius, deathPos.z + searchRadius),
                orb -> orb.isAlive() && orb.getPos().distanceTo(deathPos) <= searchRadius);

        // 💎 将经验球移动到玩家位置
        for (ExperienceOrbEntity orb : nearbyOrbs) {
            if (orb.isAlive()) {
                // 直接移动到玩家位置
                orb.setPosition(playerPos.x, playerPos.y + SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE, playerPos.z);

                // 添加向玩家移动的速度
                Vec3d velocity = playerPos.subtract(orb.getPos()).normalize()
                        .multiply(SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE);
                orb.setVelocity(velocity.x, velocity.y + 0.1, velocity.z);

                // 生成收集粒子效果
                world.spawnParticles(ParticleTypes.ENCHANT,
                        orb.getX(), orb.getY(), orb.getZ(),
                        3, 0.1, 0.1, 0.1, 0.1);
            }
        }
    }

    /**
     * 收集掉落物到玩家位置
     */
    private static void collectDroppedItems(ServerWorld world, Vec3d deathPos, Vec3d playerPos, PlayerEntity player) {
        // 🎯 搜索死亡位置附近的掉落物
        double searchRadius = 8.0; // 搜索半径8格
        List<ItemEntity> nearbyItems = world.getEntitiesByClass(
                ItemEntity.class,
                new Box(deathPos.x - searchRadius, deathPos.y - searchRadius, deathPos.z - searchRadius,
                        deathPos.x + searchRadius, deathPos.y + searchRadius, deathPos.z + searchRadius),
                item -> item.isAlive() && item.getPos().distanceTo(deathPos) <= searchRadius);

        // 📦 将掉落物移动到玩家位置
        for (ItemEntity item : nearbyItems) {
            if (item.isAlive()) {
                // 在玩家周围随机分布，避免重叠
                double offsetX = (Math.random() - SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE) * 2.0; // -1到1的随机偏移
                double offsetZ = (Math.random() - SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE) * 2.0;

                // 移动到玩家位置附近
                item.setPosition(playerPos.x + offsetX, playerPos.y + SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE,
                        playerPos.z + offsetZ);

                // 添加向玩家移动的速度
                Vec3d velocity = playerPos.subtract(item.getPos()).normalize().multiply(0.3);
                item.setVelocity(velocity.x, velocity.y + 0.1, velocity.z);

                // 重置拾取延迟，使其立即可被拾取
                item.setPickupDelay(0);

                // 生成收集粒子效果
                world.spawnParticles(ParticleTypes.CRIT,
                        item.getX(), item.getY(), item.getZ(),
                        2, 0.1, 0.1, 0.1, 0.1);
            }
        }
    }

    /**
     * 获取玩家的攻击武器（优先主手，其次副手）
     */
    public static ItemStack getPlayerWeapon(PlayerEntity player) {
        // 主手武器
        ItemStack mainHandItem = player.getMainHandStack();
        if (isWeapon(mainHandItem)) {
            return mainHandItem;
        }

        // 副手武器
        ItemStack offHandItem = player.getOffHandStack();
        if (isWeapon(offHandItem)) {
            return offHandItem;
        }

        // 创建一个空的剑物品作为默认武器
        return new ItemStack(Items.WOODEN_SWORD);
    }

    /**
     * 判断物品是否为武器
     */
    /**
     * 检测武器类型并返回对应枚举
     */
    public static WeaponType getWeaponType(ItemStack stack) {
        if (stack.isEmpty())
            return WeaponType.UNKNOWN;

        Item item = stack.getItem();
        String itemName = item.toString().toLowerCase();

        // 🗡️ 优先使用实例判断
        if (item instanceof net.minecraft.item.SwordItem) {
            return WeaponType.SWORD;
        }
        if (item instanceof TridentItem) {
            return WeaponType.TRIDENT;
        }
        if (item instanceof FishingRodItem) {
            return WeaponType.ROD;
        }
        if (item instanceof ArrowItem) {
            return WeaponType.ARROW;
        }
        if (item instanceof ToolItem) {
            return WeaponType.TOOL;
        }

        // 🎯 基于名称的详细分类
        if (itemName.contains("sword") || itemName.contains("katana") ||
                itemName.contains("blade") || itemName.contains("dagger")) {
            return WeaponType.SWORD;
        }
        if (itemName.contains("axe")) {
            return WeaponType.AXE;
        }
        if (itemName.contains("trident")) {
            return WeaponType.TRIDENT;
        }
        if (itemName.contains("bow") || itemName.contains("crossbow")) {
            return WeaponType.BOW;
        }
        if (itemName.contains("rod") || itemName.contains("fishing")) {
            return WeaponType.ROD;
        }
        if (itemName.contains("wand") || itemName.contains("staff")) {
            return WeaponType.WAND;
        }
        if (itemName.contains("arrow") || itemName.contains("spear")) {
            return WeaponType.ARROW;
        }
        if (itemName.contains("stick") || itemName.contains("club")) {
            return WeaponType.STICK;
        }
        if (itemName.contains("pickaxe") || itemName.contains("shovel") ||
                itemName.contains("hoe")) {
            return WeaponType.TOOL;
        }

        // 其他武器类型
        if (itemName.contains("knife") || itemName.contains("scythe") ||
                itemName.contains("hammer") || itemName.contains("mace") ||
                itemName.contains("flail")) {
            return WeaponType.AXE; // 归类为重武器
        }

        return WeaponType.UNKNOWN;
    }

    private static boolean isWeapon(ItemStack stack) {
        if (stack.isEmpty())
            return false;

        // 🎯 使用自定义武器分类逻辑，支持不同武器类型的粒子效果
        return getWeaponType(stack) != WeaponType.UNKNOWN;
    }

    /**
     * 计算武器的完整伤害（包括基础攻击力和锋利附魔）
     */
    private static float calculateWeaponDamage(ItemStack weapon, PlayerEntity player) {
        if (weapon.isEmpty())
            return SwordAuraConstants.YAW_CHANGE_THRESHOLD; // 空手伤害

        // 🗡️ 基础武器攻击力
        float baseDamage = SwordAuraConstants.YAW_CHANGE_THRESHOLD; // 默认空手伤害

        // 🗡️ 使用属性系统获取武器攻击力
        try {
            // 获取武器的属性修饰符
            AttributeModifiersComponent attributes = weapon.getOrDefault(
                    DataComponentTypes.ATTRIBUTE_MODIFIERS,
                    AttributeModifiersComponent.DEFAULT);

            // 查找攻击伤害属性
            for (var modifier : attributes.modifiers()) {
                if (modifier.attribute().equals(EntityAttributes.GENERIC_ATTACK_DAMAGE)) {
                    baseDamage = (float) modifier.modifier().value() + 1.0f; // +1是基础玩家攻击力
                    break;
                }
            }

            // 如果没有找到攻击伤害属性，使用默认值
            if (baseDamage == SwordAuraConstants.YAW_CHANGE_THRESHOLD) {
                if (weapon.getItem() instanceof SwordItem) {
                    baseDamage = 7.0f; // 剑类默认6攻击 + 1基础
                } else if (weapon.getItem() instanceof ToolItem) {
                    baseDamage = 4.0f; // 工具类默认3攻击 + 1基础
                }
            }
        } catch (Exception e) {
            // 如果属性获取失败，使用默认值
            if (weapon.getItem() instanceof SwordItem) {
                baseDamage = 7.0f;
            } else if (weapon.getItem() instanceof ToolItem) {
                baseDamage = 4.0f;
            }
            System.out.println("⚠️ 无法获取武器攻击力，使用默认值: " + baseDamage);
        }

        // ⚔️ 锋利附魔加成
        var enchantments = EnchantmentHelper.getEnchantments(weapon);
        for (var entry : enchantments.getEnchantments()) {
            if (entry.getKey().isPresent()) {
                String enchantId = entry.getKey().get().getValue().toString();
                if (enchantId.equals("minecraft:sharpness")) {
                    int sharpnessLevel = enchantments.getLevel(entry);
                    baseDamage += 1.5f + (sharpnessLevel * 0.5f); // 锋利：SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE +
                    // 等级*SwordAuraConstants.MAX_ENCHANTED_APPLE_CHANCE
                    SwordAuraLogger.enchantEffect("锋利", sharpnessLevel, "+" + (1.5f + sharpnessLevel * 0.5f));
                }
            }
        }

        return baseDamage;
    }

    /**
     * 获取御剑术附魔等级（支持主手和副手）
     */
    public static int getSwordAuraLevel(net.minecraft.item.ItemStack itemStack) {
        if (itemStack.isEmpty())
            return 0;

        var enchantments = EnchantmentHelper.getEnchantments(itemStack);

        for (var entry : enchantments.getEnchantments()) {
            if (entry.getKey().isPresent()) {
                String enchantmentId = entry.getKey().get().getValue().toString();
                if (enchantmentId.equals("lucifer_treasure:sword_aura")) {
                    return enchantments.getLevel(entry);
                }
            }
        }

        return 0;
    }

    /**
     * 获取玩家最高的御剑术等级（检查主手和副手）
     */
    public static int getPlayerSwordAuraLevel(PlayerEntity player) {
        int mainHandLevel = getSwordAuraLevel(player.getMainHandStack());
        int offHandLevel = getSwordAuraLevel(player.getOffHandStack());
        return Math.max(mainHandLevel, offHandLevel);
    }

    /**
     * 清理玩家数据（保留状态设置）
     */
    public static void cleanupPlayerData(UUID playerId) {
        // 只清理运行时数据，保留状态设置
        // 🔧 已移除全局攻击冷却，只保留目标攻击冷却

        FLOATING_SWORDS.entrySet().removeIf(entry -> entry.getKey().startsWith(playerId.toString()));

        // 保存当前状态
        savePlayerStates();

        // 清理新增的缓存
        NEARBY_ENEMIES_CACHE.remove(playerId);
        ATTACKING_ENEMIES_CACHE.remove(playerId);
        PLAYER_TARGET_CACHE.remove(playerId);
        MANUAL_ATTACK_TARGETS.remove(playerId); // 清理手动攻击目标
        CACHE_UPDATE_TIME.remove(playerId);

        // 🎯 清理命中率统计数据
        HIT_COUNT.remove(playerId);
        TOTAL_ATTACKS.remove(playerId);
        LAST_STATS_TIME.remove(playerId);

        // 🚀 清理新增的位置缓存
        LAST_PLAYER_POS.remove(playerId);
        LAST_PLAYER_YAW.remove(playerId);
        LAST_PARTICLE_UPDATE.remove(playerId);
        LAST_HIT_SOUND_TIME.remove(playerId);
        LAST_ENEMY_COUNT.remove(playerId);
        LAST_SWORD_COUNT.remove(playerId); // 清理剑数量缓存
        // 🚫 已移除：不再需要恢复时间缓存
    }

    /**
     * 获取御剑术状态（用于调试）
     */
    public static boolean isAuraEnabled(UUID playerId) {
        return AURA_ENABLED.getOrDefault(playerId, false);
    }

    /**
     * 切换御剑术状态（内部方法）
     */
    private static void toggleAura(PlayerEntity player) {
        UUID playerId = player.getUuid();
        boolean currentState = AURA_ENABLED.getOrDefault(playerId, false);
        boolean newState = !currentState;

        AURA_ENABLED.put(playerId, newState);

        if (newState) {
            // 开启御剑术
            player.getWorld().playSound(null, player.getX(), player.getY(), player.getZ(),
                    SoundEvents.ENTITY_EVOKER_CAST_SPELL, SoundCategory.PLAYERS,
                    1.0f, 1.0f);
            // 显示开启消息
            player.sendMessage(Text.literal("§b[御剑术] §a已开启"), true);
            SwordAuraLogger.toggleAura(SwordAuraLogger.getPlayerName(player), true, getPlayerSwordAuraLevel(player));

            // 🚀 延迟显示状态，让悬浮剑先生成
            Runnable displayStatus = () -> {
                try {
                    Thread.sleep(2000); // 等待2秒让系统稳定
                    displaySwordAuraStatus(player);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            };
            new Thread(displayStatus).start();
        } else {
            // 关闭御剑术
            disableAura(playerId);
            player.getWorld().playSound(null, player.getX(), player.getY(), player.getZ(),
                    SoundEvents.BLOCK_BEACON_DEACTIVATE, SoundCategory.PLAYERS,
                    0.8f, 1.0f);
            // 显示关闭消息
            player.sendMessage(Text.literal("§b[御剑术] §c已关闭"), true);
            SwordAuraLogger.toggleAura(SwordAuraLogger.getPlayerName(player), false, getPlayerSwordAuraLevel(player));
        }

        // 保存状态到文件
        savePlayerStates();
    }

    /**
     * 从客户端切换御剑术状态（简化版本）
     */
    public static void toggleAuraFromClient(PlayerEntity player) {
        // 在集成服务端中，直接处理
        toggleAura(player);
    }

    /**
     * 保存玩家状态到文件
     */
    private static void savePlayerStates() {
        try {
            Map<String, Boolean> stateMap = new HashMap<>();
            for (Map.Entry<UUID, Boolean> entry : AURA_ENABLED.entrySet()) {
                stateMap.put(entry.getKey().toString(), entry.getValue());
            }

            String json = GSON.toJson(stateMap);
            Files.write(Paths.get(SwordAuraConstants.CONFIG_FILE_NAME), json.getBytes());
            System.out.println("💾 已保存御剑术状态到文件");
        } catch (Exception e) {
            System.err.println("❌ 保存御剑术状态失败: " + e.getMessage());
        }
    }

    /**
     * 从文件加载玩家状态
     */
    private static void loadPlayerStates() {
        try {
            Path configPath = Paths.get(SwordAuraConstants.CONFIG_FILE_NAME);
            if (Files.exists(configPath)) {
                String json = new String(Files.readAllBytes(configPath));
                java.lang.reflect.Type mapType = new TypeToken<Map<String, Boolean>>() {
                }.getType();
                Map<String, Boolean> stateMap = GSON.fromJson(json, mapType);

                if (stateMap != null) {
                    AURA_ENABLED.clear();
                    for (Map.Entry<String, Boolean> entry : stateMap.entrySet()) {
                        UUID playerId = UUID.fromString(entry.getKey());
                        AURA_ENABLED.put(playerId, entry.getValue());
                    }
                    System.out.println("💾 已从文件加载御剑术状态");
                }
            }
        } catch (Exception e) {
            System.err.println("❌ 加载御剑术状态失败: " + e.getMessage());
        }
    }

    // 🚀 新增：悬浮剑状态查询和显示功能

    /**
     * 获取玩家当前悬浮剑数量 - 线程安全版本
     */
    public static int getCurrentFloatingSwordCount(UUID playerId) {
        try {
            // 使用防护性拷贝避免并发修改异常
            return (int) new HashMap<>(FLOATING_SWORDS).entrySet().stream()
                    .filter(entry -> entry.getValue().playerId.equals(playerId))
                    .count();
        } catch (Exception e) {
            System.err.println("❌ 获取悬浮剑数量时出错: " + e.getMessage());
            return 0;
        }
    }

    /**
     * 获取玩家当前可见的悬浮剑数量（不包括恢复中的剑）- 用于HUD显示
     */
    public static int getVisibleFloatingSwordCount(UUID playerId) {
        try {
            // 使用防护性拷贝避免并发修改异常
            return (int) new HashMap<>(FLOATING_SWORDS).entrySet().stream()
                    .filter(entry -> entry.getValue().playerId.equals(playerId))
                    .filter(entry -> !entry.getValue().isVisuallyRecovering) // 过滤掉恢复中的剑
                    .count();
        } catch (Exception e) {
            System.err.println("❌ 获取可见悬浮剑数量时出错: " + e.getMessage());
            return 0;
        }
    }

    /**
     * 获取玩家当前击中特效剑数量 - 线程安全版本
     */
    public static int getCurrentHitEffectSwordCount(UUID playerId) {
        try {
            // 使用防护性拷贝避免并发修改异常
            return (int) new HashMap<>(HIT_EFFECT_SWORDS).entrySet().stream()
                    .filter(entry -> entry.getValue().playerId.equals(playerId))
                    .count();
        } catch (Exception e) {
            System.err.println("❌ 获取击中特效剑数量时出错: " + e.getMessage());
            return 0;
        }
    }

    /**
     * 获取玩家当前恢复中的剑数量 - 线程安全版本
     */
    public static int getCurrentRecoveringSwordCount(UUID playerId) {
        try {
            // 使用防护性拷贝避免并发修改异常
            return (int) new HashMap<>(FLOATING_SWORDS).entrySet().stream()
                    .filter(entry -> entry.getValue().playerId.equals(playerId))
                    .filter(entry -> entry.getValue().isVisuallyRecovering) // 计算恢复中的剑
                    .count();
        } catch (Exception e) {
            System.err.println("❌ 获取恢复中剑数量时出错: " + e.getMessage());
            return 0;
        }
    }

    /**
     * 显示玩家御剑术详细状态
     */
    public static void displaySwordAuraStatus(PlayerEntity player) {
        UUID playerId = player.getUuid();
        boolean isEnabled = AURA_ENABLED.getOrDefault(playerId, false);
        int auraLevel = getPlayerSwordAuraLevel(player);
        int floatingSwords = getCurrentFloatingSwordCount(playerId);
        int hitEffectSwords = getCurrentHitEffectSwordCount(playerId);
        ItemStack weapon = getPlayerWeapon(player);
        WeaponType weaponType = getWeaponType(weapon);

        System.out.println("=== 🗡️ 御剑术状态详情 ===");
        System.out.println("玩家: " + player.getName().getString());
        System.out.println("御剑术状态: " + (isEnabled ? "✅ 开启" : "❌ 关闭"));
        System.out.println("附魔等级: " + (auraLevel > 0 ? auraLevel + " 级" : "无"));
        System.out.println("当前武器: " + (weapon.isEmpty() ? "无" : weapon.getName().getString()));
        System.out.println("武器类型: " + weaponType.displayName);
        System.out.println("悬浮剑数量: " + floatingSwords + "/" + auraLevel);
        System.out.println("击中特效剑: " + hitEffectSwords);

        // 击中率统计
        Integer hits = HIT_COUNT.get(playerId);
        Integer attacks = TOTAL_ATTACKS.get(playerId);
        if (hits != null && attacks != null && attacks > 0) {
            double hitRate = (double) hits / attacks * 100;
            System.out.println("命中率: " + hits + "/" + attacks + " (" + String.format("%.1f", hitRate) + "%)");
        } else {
            System.out.println("命中率: 暂无数据");
        }

        // 缓存信息
        Set<LivingEntity> nearbyEnemies = NEARBY_ENEMIES_CACHE.get(playerId);
        Set<LivingEntity> attackingEnemies = ATTACKING_ENEMIES_CACHE.get(playerId);
        LivingEntity playerTarget = PLAYER_TARGET_CACHE.get(playerId);

        System.out.println("附近敌人: " + (nearbyEnemies != null ? nearbyEnemies.size() : 0));
        System.out.println("攻击敌人: " + (attackingEnemies != null ? attackingEnemies.size() : 0));
        System.out.println("玩家目标: " + (playerTarget != null ? playerTarget.getName().getString() : "无"));
        System.out.println("=======================");
    }

    /**
     * 🚨 紧急功能：强制恢复所有悬浮剑
     * 如果恢复系统出现问题，可以调用此方法立即恢复所有剑
     */
    public static void forceRecoverAllSwords(PlayerEntity player) {
        UUID playerId = player.getUuid();
        int auraLevel = getPlayerSwordAuraLevel(player);

        if (auraLevel <= 0) {
            player.sendMessage(Text.literal("§c你没有御剑术附魔，无法强制恢复剑"), false);
            return;
        }

        // 清理所有恢复队列
        Iterator<Map.Entry<String, Long>> iterator = SWORD_RECOVERY_QUEUE.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Long> entry = iterator.next();
            if (entry.getKey().startsWith(playerId.toString())) {
                iterator.remove();
            }
        }

        // 重新维护悬浮剑
        if (player.getWorld() instanceof ServerWorld serverWorld) {
            maintainFloatingSwords(serverWorld, player, auraLevel);
        }

        // 显示恢复信息
        int currentSwordCount = getCurrentFloatingSwordCount(playerId);
        int expectedSwordCount = calculateSwordCount(auraLevel);

        String message = String.format("§a强制恢复完成！当前剑数：%d/%d", currentSwordCount, expectedSwordCount);
        player.sendMessage(Text.literal(message), false);

        SwordAuraLogger.log(SwordAuraLogger.LogLevel.INFO, SwordAuraLogger.Category.SWORD_MANAGEMENT,
                String.format("[%s] 强制恢复所有剑 - 当前:%d 预期:%d",
                        SwordAuraLogger.getPlayerName(player), currentSwordCount, expectedSwordCount));
    }

    /**
     * 🛡️ 检查PvP攻击是否被允许
     */
    private static boolean isPvPAttackAllowed(PlayerEntity attacker, LivingEntity target, ServerWorld world) {
        return SwordAuraPvPSystem.isPvPAttackAllowed(attacker, target, world);
    }

    /**
     * 🛡️ 重置PvP计数器
     */
    private static void resetPvPCounters(UUID playerId, long currentTime) {
        // 这个方法现在由PVP系统内部处理，不需要显式调用
        // 保留这个方法是为了兼容性
    }

    /**
     * 🔄 建立PVP敌对关系
     */
    private static void establishHostility(PlayerEntity attacker, PlayerEntity target, ServerWorld world) {
        SwordAuraPvPSystem.establishHostility(attacker, target, world);
    }

    /**
     * 🎯 获取玩家的敌对关系信息
     */
    public static java.util.List<SwordAuraPvPSystem.HostilityInfo> getPlayerHostilities(PlayerEntity player) {
        return SwordAuraPvPSystem.getPlayerHostilities(player);
    }

    /**
     * 🧹 清理过期的PVP敌对关系
     */
    private static void cleanupExpiredHostility(long currentTime) {
        // 由PVP系统处理
    }

    /**
     * 🔍 检查是否为有效的PvP目标
     */
    private static boolean isValidPvPTarget(LivingEntity entity, PlayerEntity attacker) {
        // 重定向到PVP系统（如果需要的话）
        return entity instanceof PlayerEntity;
    }

    /**
     * 🧪 调试方法：添加模拟敌对关系
     */
    public static void addTestHostility(PlayerEntity player, String fakePlayerName, boolean isOutgoing,
                                        int remainingSeconds) {
        SwordAuraPvPSystem.addTestHostility(player, fakePlayerName, isOutgoing, remainingSeconds);
    }

    /**
     * 🧹 清理所有敌对关系
     */
    public static void clearAllHostilities() {
        SwordAuraPvPSystem.clearAllHostilities();
    }

    /**
     * 🧪 创建测试敌对关系
     */
    public static void createTestHostilities(PlayerEntity player) {
        SwordAuraPvPSystem.createTestHostilities(player);
    }

    /**
     * 💀 清理指定玩家的所有敌对关系
     */
    public static int clearAllPlayerHostilities(UUID playerId) {
        return SwordAuraPvPSystem.clearAllPlayerHostilities(playerId);
    }
}
